I am developing WPF Touch Screen Keyboard.
I need to know how is it possible to make main window non focusable, so other windows will be receiving the input when I click on virtual keyboard buttons.
Simple applying "Focusable="False"" to the main window and all child controls doesn't work.
I think there is a clickable attribute you can set to false which stops the form receiving click messages.
Problem was solved by using Popup instead of Window, which not grab the focus, when you click on it.
From here: https://social.msdn.microsoft.com/Forums/vstudio/en-US/41ca3605-247c-4c5b-ac5d-74ce5abd7b92/making-a-window-invisible-to-mouse-events-ishittestvisiblefalse-not-working?forum=wpf
I've figured out how to do this. The key being the WS_EX_TRANSPARENT flag for the window's extended style.You can set the topmost property like you normally would, then this code takes care of making the window transparent to mouse clicks:
Code Snippet
public const int WS_EX_TRANSPARENT = 0x00000020;
public const int GWL_EXSTYLE = (-20);
[DllImport("user32.dll")]
public static extern int GetWindowLong(IntPtr hwnd, int index);
[DllImport("user32.dll")]
public static extern int SetWindowLong(IntPtr hwnd, int index, int newStyle);
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
// Get this window's handle
IntPtr hwnd = new WindowInteropHelper(this).Handle;
// Change the extended window style to include WS_EX_TRANSPARENT
int extendedStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
SetWindowLong(hwnd, GWL_EXSTYLE, extendedStyle | WS_EX_TRANSPARENT);
}
Related
I've got a borderless movable form (dragged around by clicking and holding a mouse button). The dragging only works when I click on the form empty spaces, e.g. margin/padding area. How do I render a control (let's say label) so that it doesn't capture mouse events, but instead passes it to the underlying form element? In other words, I want to click on this label element and drag the form.
The closest thing I can think of is pointer-events: none in CSS.
Here's the powershell code I use to make my form movable:
function makeFormDraggable {
param($form)
Add-Type '
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
public class User32{
//const and dll functions for moving form
public const int WM_NCLBUTTONDOWN = 0xA1;
public const int HT_CAPTION = 0x2;
[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
[DllImport("user32.dll")]
public static extern bool ReleaseCapture();
}
'
$onMouseDown = [System.Windows.Forms.MouseEventHandler] {
#Event Argument: $_ = [System.Windows.Forms.MouseEventArgs]
[user32]::ReleaseCapture()
[user32]::SendMessage($form.Handle, [user32]::WM_NCLBUTTONDOWN, [user32]::HT_CAPTION, 0);
}
$form.Add_MouseDown($onMouseDown)
}
I know that there are many questions about hiding or removing the icon from the upper left corner of a WPF window, the place where the system menu is. I've tried many of them but none works. Here are my requirements:
The icon disappears and does not take any empty space (i. e. no transparent icon)
The window title starts directly at the left edge of the window
The close button in the upper right corner is still there and works
Minimise/maximise buttons are still there if enabled (optional, didn't test this)
No custom-drawing of the entire window frame
Works on Windows 7 with Aero Glass enabled (Windows 8 anybody?)
Works on 32 and 64 bit Windows (x86 and x64 build)
Works with WPF .NET 4.0
Works when not in a debugger like Visual Studio (would be nice if it also works in the debugger)
Should also work on Windows XP (optional)
The available answers basically use the Windows API functions GetWindowLong, SetWindowLong and sometimes also SetWindowPos to add the extended window style WS_EX_DLGMODALFRAME and call SWP_FRAMECHANGED. Sometimes, other styles are also set or unset.
Unfortunately, none of this works at all. I can either have no icon with no close button, or both are still there. But it's also noticeable that all of that content is from 2010 or eariler. It seems it's targeted at earlier .NET or Windows versions and fails since.
I've already compared the window styles of system dialogs (from Explorer) and my WPF windows with Microsoft Spy++ (included in Visual Studio). But I can try to set all flags the same, the icon won't go away. It's like black magic that overrules every other API function or physics.
Does anybody have a solution that still works today and in the indicated environment?
If you had just put the words in your title into a search engine instead of here as I just did, then you would have found many more results than these. You can find your answer in the following:
Removing Icon from a WPF window
Is it possible to display a wpf window without an icon in the title bar?
How to remove the icon of a WPF window
How to remove Icon from window titlebar
How to hide window icon in WPF
Your last comment about this not working on large scale applications made me wonder. As such, I then added the code to a large scale application and once again it worked just fine. However, I continued to test this and you must be using a RibbonWindow in your application, because when I tested this code on a large scale application with a RibbonWindow the code did not work.
If you are using a normal Window then give this code a try (From #MichalCiechan's answer to the first linked post):
First add this class:
public static class IconHelper
{
[DllImport("user32.dll")]
static extern int GetWindowLong(IntPtr hwnd, int index);
[DllImport("user32.dll")]
static extern int SetWindowLong(IntPtr hwnd, int index, int newStyle);
[DllImport("user32.dll")]
static extern bool SetWindowPos(IntPtr hwnd, IntPtr hwndInsertAfter, int x,
int y, int width, int height, uint flags);
[DllImport("user32.dll")]
static extern IntPtr SendMessage(IntPtr hwnd, uint msg, IntPtr wParam, IntPtr
lParam);
const int GWL_EXSTYLE = -20;
const int WS_EX_DLGMODALFRAME = 0x0001;
const int SWP_NOSIZE = 0x0001;
const int SWP_NOMOVE = 0x0002;
const int SWP_NOZORDER = 0x0004;
const int SWP_FRAMECHANGED = 0x0020;
const uint WM_SETICON = 0x0080;
public static void RemoveIcon(Window window)
{
// Get this window's handle
IntPtr hwnd = new WindowInteropHelper(window).Handle;
// Change the extended window style to not show a window icon
int extendedStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
SetWindowLong(hwnd, GWL_EXSTYLE, extendedStyle | WS_EX_DLGMODALFRAME);
// Update the window's non-client area to reflect the changes
SetWindowPos(hwnd, IntPtr.Zero, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
SWP_NOZORDER | SWP_FRAMECHANGED);
}
}
Then add this to MainWindow.xaml.cs:
protected override void OnSourceInitialized(EventArgs e)
{
IconHelper.RemoveIcon(this);
}
Oh... and one other thing to note... it won't work if you have set the Window.Icon property, but I'm guessing that you haven't done that if you don't want an icon to appear.
The above does not work, when creating a dialog window from a WPF application having an icon.
However, when adding the following two lines, the icon correctly vanishes from the dialog window:
SendMessage(hwnd, WM_SETICON, new IntPtr(1), IntPtr.Zero);
SendMessage(hwnd, WM_SETICON, IntPtr.Zero, IntPtr.Zero);
(s.a. https://connect.microsoft.com/VisualStudio/feedback/details/745230/wpf-window-cannot-be-displayed-without-titlebar-icon)
This is what I came up with after seeing different solutions to this question:
internal const int SWP_NOSIZE = 0x0001;
internal const int SWP_NOMOVE = 0x0002;
internal const int SWP_NOZORDER = 0x0004;
internal const int SWP_FRAMECHANGED = 0x0020;
internal const int GWL_EXSTYLE = -20;
internal const int WS_EX_DLGMODALFRAME = 0x0001;
[DllImport("user32.dll", SetLastError = true)]
internal static extern int GetWindowLong(IntPtr hWnd, int nIndex);
[DllImport("user32.dll")]
internal static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
[DllImport("user32.dll")]
internal static extern bool SetWindowPos(IntPtr hwnd, IntPtr hwndInsertAfter, int x, int y, int width, int height, uint flags);
/// <summary>
/// Hides icon for window.
/// If this is called before InitializeComponent() then the icon will be completely removed from the title bar
/// If this is called after InitializeComponent() then an empty image is used but there will be empty space between window border and title
/// </summary>
/// <param name="window">Window class</param>
internal static void HideIcon(this Window window)
{
if (window.IsInitialized)
{
window.Icon = BitmapSource.Create(1, 1, 96, 96, PixelFormats.Bgra32, null, new byte[] {0, 0, 0, 0}, 4);
}
else
{
window.SourceInitialized += delegate
{
// Get this window's handle
var hwnd = new WindowInteropHelper(window).Handle;
// Change the extended window style to not show a window icon
int extendedStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
SetWindowLong(hwnd, GWL_EXSTYLE, extendedStyle | WS_EX_DLGMODALFRAME);
// Update the window's non-client area to reflect the changes
SetWindowPos(hwnd, IntPtr.Zero, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
};
}
}
Example:
public partial class ExampleWindow : Window
{
public ExampleWindow()
{
// Hides icon completely
this.HideIcon();
InitializeComponent();
}
}
I've a little problem about focus on WPF.
I whant to create a window, always on top, and that never get the focus (even if we click on it).
Here's my solution :
public partial class SkinWindow : Window
{
public SkinWindow()
{
InitializeComponent();
Loaded += ( object sender, RoutedEventArgs e ) => SetNoActiveWindow();
}
private void SetNoActiveWindow()
{
WindowInteropHelper helper = new WindowInteropHelper( this );
SetWindowLong( helper.Handle, GWL_EXSTYLE, WS_EX_NOACTIVATE );
LockSetForegroundWindow( LSFW_LOCK );
}
const int GWL_EXSTYLE = -20;
const int WS_EX_NOACTIVATE = 134217728;
const int LSFW_LOCK = 1;
[DllImport( "user32" )]
public static extern bool LockSetForegroundWindow( uint UINT );
[DllImport( "user32" )]
public static extern IntPtr SetWindowLong( IntPtr hWnd, int nIndex, int dwNewLong );
}
First problem : It's works, but I've to select an other window to "remove" the focus of my application (after the focus is not gave again, even if I click on my window).
Second problem : When I move or resize the window, the modifications happens when I drop the window.
Do you have any ideas / links / docs ?
Thank you :)
You might want to have a look at this SO post: Make a form not focusable in C#. The answer is specific to Windows Forms. However, the main part is done using Win32 functions, so maybe you can get some ideas from there...
WPF doesn't provide the ability to have a window that allows resize but doesn't have maximize or minimize buttons. I'd like to able to make such a window so I can have resizable dialog boxes.
I'm aware the solution will mean using pinvoke but I'm not sure what to call and how. A search of pinvoke.net didn't turn up any thing that jumped out at me as what I needed, mainly I'm sure because Windows Forms does provide the CanMinimize and CanMaximize properties on its windows.
Could someone point me towards or provide code (C# preferred) on how to do this?
I've stolen some code I found on the MSDN forums and made an extension method on the Window class, like this:
internal static class WindowExtensions
{
// from winuser.h
private const int GWL_STYLE = -16,
WS_MAXIMIZEBOX = 0x10000,
WS_MINIMIZEBOX = 0x20000;
[DllImport("user32.dll")]
extern private static int GetWindowLong(IntPtr hwnd, int index);
[DllImport("user32.dll")]
extern private static int SetWindowLong(IntPtr hwnd, int index, int value);
internal static void HideMinimizeAndMaximizeButtons(this Window window)
{
IntPtr hwnd = new System.Windows.Interop.WindowInteropHelper(window).Handle;
var currentStyle = GetWindowLong(hwnd, GWL_STYLE);
SetWindowLong(hwnd, GWL_STYLE, (currentStyle & ~WS_MAXIMIZEBOX & ~WS_MINIMIZEBOX));
}
}
The only other thing to remember is that for some reason this doesn't work from a window's constructor. I got around that by chucking this into the constructor:
this.SourceInitialized += (x, y) =>
{
this.HideMinimizeAndMaximizeButtons();
};
One way is to set your ResizeMode="NoResize". It will behave like this.
Don't know if this works for your req. visually.. This is
<Window x:Class="DataBinding.MyWindow" ...Title="MyWindow" Height="300" Width="300"
WindowStyle="ToolWindow" ResizeMode="CanResizeWithGrip">
If anyone use Devexpress window (DXWindow) accepted answer doesn't work. One ugly approach is
public partial class MyAwesomeWindow : DXWindow
{
public MyAwesomeWIndow()
{
Loaded += OnLoaded;
}
private void OnLoaded(object sender, RoutedEventArgs routedEventArgs)
{
// hides maximize button
Button button = (Button)DevExpress.Xpf.Core.Native.LayoutHelper.FindElementByName(this, DXWindow.ButtonParts.PART_Maximize.ToString());
button.IsHitTestVisible = false;
button.Opacity = 0;
// hides minimize button
button = (Button)DevExpress.Xpf.Core.Native.LayoutHelper.FindElementByName(this, DXWindow.ButtonParts.PART_Minimize.ToString());
button.IsHitTestVisible = false;
button.Opacity = 0;
// hides close button
button = (Button)DevExpress.Xpf.Core.Native.LayoutHelper.FindElementByName(this, DXWindow.ButtonParts.PART_CloseButton.ToString());
button.IsHitTestVisible = false;
button.Opacity = 0;
}
}
Here's a solution I'm using. Note that maximize button is still displayed.
Markup:
<Window x:Class="Example"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Example"
StateChanged="Window_StateChanged">
Code behind:
// Disable maximizing this window
private void Window_StateChanged(object sender, EventArgs e)
{
if (this.WindowState == WindowState.Maximized)
this.WindowState = WindowState.Normal;
}
This variant of the solution proposed by #MattHamilton can (and must) be called in the constructor of the Window. The trick is to subscribe a delegate to the SourceInitialized event within the extension method.
private const int GWL_STYLE = -16, WS_MAXIMIZEBOX = 0x10000, WS_MINIMIZEBOX = 0x20000;
[DllImport("user32.dll")]
extern private static int GetWindowLong(IntPtr hwnd, int index);
[DllImport("user32.dll")]
extern private static int SetWindowLong(IntPtr hwnd, int index, int value);
/// <summary>
/// Hides the Minimize and Maximize buttons in a Window. Must be called in the constructor.
/// </summary>
/// <param name="window">The Window whose Minimize/Maximize buttons will be hidden.</param>
public static void HideMinimizeAndMaximizeButtons(this Window window)
{
window.SourceInitialized += (s, e) => {
IntPtr hwnd = new System.Windows.Interop.WindowInteropHelper(window).Handle;
int currentStyle = GetWindowLong(hwnd, GWL_STYLE);
SetWindowLong(hwnd, GWL_STYLE, currentStyle & ~WS_MAXIMIZEBOX & ~WS_MINIMIZEBOX);
};
}
You can set the ResizeMode="NoResize" of the window if you want to remove Minimize and Maximize button
Just use
WindowStyle="ToolWindow"
It hides the maximize and minimize buttons, but the window can still be resized by dragging the window borders and minimize using the hide button in the bottom right corner of the taskbar.
https://learn.microsoft.com/en-us/dotnet/api/system.windows.window.windowstyle?view=windowsdesktop-6.0
I have a C# WinForms borderless window, for which I override WndProc and handle the WM_NCHITTEST message. For an area of that form, my hit test function returns HTSYSMENU. Double-clicking that area successfully closes the form, but right-clicking it does not show the window's system menu, nor does it show up when right-clicking the window's name in the taskbar.
This form uses these styles:
this.SetStyle( ControlStyles.AllPaintingInWmPaint, true );
this.SetStyle( ControlStyles.UserPaint, true );
this.SetStyle( ControlStyles.OptimizedDoubleBuffer, true );
this.SetStyle( ControlStyles.ResizeRedraw, true );
And has these non-default property values:
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
this.KeyPreview = true;
this.MaximizeBox = false;
this.MinimizeBox = false;
I've tried handling WM_NCRBUTTONDOWN and WM_NCRBUTTONUP, and send the WM_GETSYSMENU message, but it didn't work.
A borderless window, if I am not mistaken, is flagged such that it offers no system menu, and that it does not appear in the taskbar.
The fact that any given window does not have a border and does not appear in the taskbar is the result of the style flags set on the window. These particular Style flags can be set using the GetWindowLong and SetWindowLong API calls. However you have to be careful as certain styles just don't work together.
I have written a number of custom controls over the years and I am constantly coaxing windows to become something they weren't originally intended to be.
For example I have written my own dropdown control where I needed a window to behave as a popup and not to activate.
The following code will do that. Note that the code appears in the OnHandleCreated event handler. This is because the flags need to be changed just after the handle is setup which indicates that Windows has already set what it thinks the flags should be.
using System.Runtime.InteropServices;
protected override void OnHandleCreated(EventArgs e) {
uint dwWindowProperty;
User32.SetParent(this.Handle, IntPtr.Zero);
dwWindowProperty = User32.GetWindowLong( this.Handle, User32.GWL.EXSTYLE );
dwWindowProperty = dwWindowProperty | (uint)User32.WSEX.TOOLWINDOW | (uint)User32.WSEX.NOACTIVATE;
User32.SetWindowLong( this.Handle, User32.GWL.EXSTYLE, dwWindowProperty );
dwWindowProperty = User32.GetWindowLong( this.Handle, User32.GWL.STYLE );
dwWindowProperty = ( dwWindowProperty & ~(uint)User32.WS.CHILD ) | (uint)User32.WS.POPUP;
User32.SetWindowLong( this.Handle, User32.GWL.STYLE, dwWindowProperty );
base.OnHandleCreated (e);
}
//this is a fragment of my User32 library wrapper needed for the previous code segment.
class User32
{
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
[DllImport("user32.dll", CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall )]
public static extern int SetWindowLong( IntPtr hWnd, User32.GWL gwlIndex, uint dwNewLong);
[DllImport("user32.dll", CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall )]
public static extern uint GetWindowLong( IntPtr hWnd, User32.GWL gwlIndex );
[FlagsAttribute]
public enum WS: uint {
POPUP = 0x80000000,
CHILD = 0x40000000,
}
public enum GWL {
STYLE = -16,
EXSTYLE = -20
}
[FlagsAttribute]
public enum WSEX: uint {
TOP = 0x0,
TOPMOST = 0x8,
TOOLWINDOW = 0x80,
NOACTIVATE = 0x08000000,
}
}
Unfortunately the SysMenu style cannot be set without using the Caption style, so I can't say if this is a problem in your implementation.
You can check out the original style list and the extend style list at these two links:
Window Styles
CreateWindowEx
I have the same properties in my application and Right click doesn't work either, so this is not your problem, it appears to be the way windows forms respond when they have no border.
If you set your border to the normal value, you will be able to have right click in the taskbar and such.
For right click on other controls, you'll need to set the ContextMenuStrip and provide your "menu". But I'm not sure if this works when you have it without border. I have been unable to make it work.
protected override void WndProc( ref System.Windows.Forms.Message m )
{ // RightClickMenu
if ( m.Msg == 0x313 )
{
this.contextMenuStrip1.Show(this, this.PointToClient(new Point(m.LParam.ToInt32())));
}}
This detects rightclick on the applications taskbar "area"..
maybe it will help ?