I am developing a single-window app on Windows with Unity.
I allow a user to resize the window but the aspect ratio must be kept.
I want to prevent fullscreen and halfscreen, because they break the aspect ratio.
I've found the following operations make an app fullscreen or halfscreen.
fullscreen:
clicking a maximize button on the title bar
dragging the window to top of screen
pressing Alt + Enter key
pressing Windows + Up-Arrow key
halfscreen:
dragging the window to left/right of screen
pressing Windows + Left/Right -Arrow key
I want to disable all of them.
This can disable a maximize button on the title bar.
HandleRef hWnd = new HandleRef(null, GetActiveWindow());
long style = GetWindowLong(hWnd, GWL_STYLE);
style &= ~WS_MAXIMIZEBOX;
SetWindowLong(hWnd, GWL_STYLE, style);
And this can disable Windows + Up-Arrow key.
private static IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
{
switch (msg)
{
case WM_SYSCOMMAND:
if (wParam.ToInt32() == SC_MAXIMIZE) {
return IntPtr.Zero;
}
break;
}
return CallWindowProc(oldWndProcPtr, hWnd, msg, wParam, lParam);
}
But the other operations still work.
How can I disable the other operations?
private static IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
{
switch (msg)
{
case WM_SYSCOMMAND:
if (wParam.ToInt32() == SC_MAXIMIZE) {
return IntPtr.Zero;
}
break;
// BY PASS *** Alt + Enter ***
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
if (wParam == VK_RETURN)
if ((HIWORD(lParam) & KF_ALTDOWN))
return 0;
break;
}
return CallWindowProc(oldWndProcPtr, hWnd, msg, wParam, lParam);
}
Related
This is basically a simple question.
I want to update the label dynamically when I press the capslock and numlock keys while the main form is open in the WinForm application on the .net platform. How can I do this?
You have to listen for keypress callbacks like that
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
{
Keys k = (Keys)Marshal.ReadInt32(lParam);
if (k == Keys.Capital)
{
label1.Text = "Heureka";
}
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
In C#, I write code to detect arrival/removal of device information from Serial Port.
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
const int WM_DEVICECHANGE = 0x0219;
// System detects a new device
const int DBT_DEVICEARRIVAL = 0x8000;
// The device has been succesfully removed from the system
const int DBT_DEVICEREMOVECOMPLETE = 0x8004;
if (msg == WM_DEVICECHANGE)
{
switch (wParam.ToInt32())
{
case DBT_DEVICEARRIVAL:
MessageBox.Show("New device added");
break;
case DBT_DEVICEREMOVECOMPLETE:
MessageBox.Show("An device has been removed from system");
break;
default:
break;
}
}
return IntPtr.Zero;
}
I searched on Google and I founded this article.
http://www.codeproject.com/Articles/60579/A-USB-Library-to-Detect-USB-Devices
It gives me exactly the code I need to write. But I have to provide to it a PID and VID.
So that, I need to combine my code with above code to make an program that automatically show information about arrival/removal of a device.
My problems is: From the WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled), how to extract the device's VID and PID?.
I want to simulate a mouseclick at a specific position inside a window that is hidden. So no maximizing the window or moving the mouse. I just want to send the right message.
Now I tried something like this
DllImport("user32.dll")]
public static extern int PostMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam);
static int WM_LBUTTONDOWN = 0x0201;
static int WM_LBUTTONUP = 0x0202;
private static IntPtr MakeLParam(int LoWord, int HiWord)
{
return (IntPtr)((HiWord << 16) | (LoWord & 0xffff));
}
public static void test()
{
int windowPtr = FindWindow(null, "Calculator");
Console.WriteLine("pointer: " + windowPtr);
int x = 260;
int y = 180;
IntPtr lParam = MakeLParam(x, y);
IntPtr windowPointer = new IntPtr(windowPtr);
PostMessage(windowPointer, WM_LBUTTONDOWN, IntPtr.Zero, lParam);
PostMessage(windowPointer, WM_LBUTTONUP, IntPtr.Zero, lParam);
}
I expected this program to click the 8 on the calculator ( if you set it to scientific ), but it doesn't do that.
How can I simulate that click? Please don't suggest finding the windows-control-element for the "8"-Button, this is not what I am trying to do here.
I want to handle mouse click in a native MFC application from a C# application.
To do so I'm trying to subclass the native application. I don't get any errors, but the wndproc are newer invoked.
private const int GwlWndProc = -4;
private delegate int Win32WndProc(IntPtr hWnd, int msg, int wParam, int lParam);
[DllImport("user32")]
private static extern IntPtr SetWindowLong(IntPtr hWnd, int nIndex, Win32WndProc newProc);
Win32WndProc _newWndProc = MyWndProc;
SetLastError(0);
IntPtr oldWndProc = SetWindowLong(hWnd, GwlWndProc, _newWndProc);
if (oldWndProc == IntPtr.Zero)
{
int errorCode = Marshal.GetLastWin32Error();
if (errorCode != 0)
throw new Win32Exception(errorCode);
}
private int MyWndProc(IntPtr hWnd, int msg, int wParam, int lParam)
{
Debug.WriteLine("MyWndProc " + (WindowsMessage)msg);
if (msg == (int) WindowsMessage.LeftButtonDown)
{
MessageBox.Show("Clicked");
return 0;
}
else return CallWindowProc(_subclasses[hWnd], hWnd, msg, wParam, lParam);
}
Edit:
To get the hWnd I use GetForegroundWindow()
What I try to do is is to prevent the application to get the mouse click
I think you need to use hooking because SetWindowLong does not work across different processes: have a look here http://www.codeproject.com/Articles/5264/Cross-Process-Subclassing
I am trying to create a WPF window with WindowStyle="None" (for custom buttons and no title) that cannot be resized. Setting ResizeMode to NoResize removes the aero border, which I want to keep.
I could set the min/max size properties and be done with it, except that:
The resize cursors are still visible, and
The window is displayed in response to a user action and fits to its contents. It displays an image, so the size changes.
So, I have a simple scheme that gets me 99% of the way there:
public class BorderedWindowNoResize : Window
{
[DllImport( "DwmApi.dll" )]
public static extern int DwmExtendFrameIntoClientArea(
IntPtr hwnd,
ref MARGINS pMarInset );
[DllImport( "user32.dll", CharSet = CharSet.Auto )]
public static extern IntPtr DefWindowProc(
IntPtr hWnd,
int msg,
IntPtr wParam,
IntPtr lParam );
public BorderedWindowNoResize()
{
Loaded += BorderedWindowNoResize_Loaded;
}
private void BorderedWindowNoResize_Loaded( object sender, RoutedEventArgs e )
{
IntPtr mainWindowPtr = new WindowInteropHelper( this ).Handle;
HwndSource mainWindowSrc = HwndSource.FromHwnd( mainWindowPtr );
mainWindowSrc.AddHook( WndProc );
}
private IntPtr WndProc( IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled )
{
var htLocation = DefWindowProc( hwnd, msg, wParam, lParam ).ToInt32();
if( msg == (uint)WM.NCHITTEST )
{
handled = true;
switch( htLocation )
{
case (int)HitTestResult.HTBOTTOM:
case (int)HitTestResult.HTBOTTOMLEFT:
case (int)HitTestResult.HTBOTTOMRIGHT:
case (int)HitTestResult.HTLEFT:
case (int)HitTestResult.HTRIGHT:
case (int)HitTestResult.HTTOP:
case (int)HitTestResult.HTTOPLEFT:
case (int)HitTestResult.HTTOPRIGHT:
htLocation = (int)HitTestResult.HTBORDER;
break;
}
}
return new IntPtr( htLocation );
}
}
Basically;
Override the window procedure.
Call the default window procedure.
If the message it is WM_NCHITTEST, check for the border results.
If it is a border, return the regular HTBORDER.
This works as far as allowing me to keep the aero window border and hiding the resize cursor(s), but it adds a ~5 pixel white border to the inside of my window.
In fact, even if I return the default windows procedure result at the top of WndPrc and do nothing else the border is still there. I need a different background color on my window, so this won't work for me.
Any ideas? Thanks in advance as always.
When you add your hook, you should only handle the messages you need to, and ignore the others. I believe you are handling certain messages twice, since you call DefWindowProc, but never set the handled parameter to true.
So in your case, you'd use:
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) {
if (msg == (uint)WM.NCHITTEST) {
handled = true;
var htLocation = DefWindowProc(hwnd, msg, wParam, lParam).ToInt32();
switch (htLocation) {
case (int)HitTestResult.HTBOTTOM:
case (int)HitTestResult.HTBOTTOMLEFT:
case (int)HitTestResult.HTBOTTOMRIGHT:
case (int)HitTestResult.HTLEFT:
case (int)HitTestResult.HTRIGHT:
case (int)HitTestResult.HTTOP:
case (int)HitTestResult.HTTOPLEFT:
case (int)HitTestResult.HTTOPRIGHT:
htLocation = (int)HitTestResult.HTBORDER;
break;
}
return new IntPtr(htLocation);
}
return IntPtr.Zero;
}
Also, I'd probably add the hook in an OnSourceInitialized override, like so:
protected override void OnSourceInitialized(EventArgs e) {
base.OnSourceInitialized(e);
IntPtr mainWindowPtr = new WindowInteropHelper(this).Handle;
HwndSource mainWindowSrc = HwndSource.FromHwnd(mainWindowPtr);
mainWindowSrc.AddHook(WndProc);
}
You can try from anywhere in a WPF App
ComponentDispatcher.ThreadFilterMessage += new ThreadMessageEventHandler(ComponentDispatcherThreadFilterMessage);
and:
// ******************************************************************
private static void ComponentDispatcherThreadFilterMessage(ref MSG msg, ref bool handled)
{
if (!handled)
{
if (msg.message == WmHotKey)
{
HotKey hotKey;
if (_dictHotKeyToCalBackProc.TryGetValue((int)msg.wParam, out hotKey))
{
if (hotKey.Action != null)
{
hotKey.Action.Invoke(hotKey);
}
handled = true;
}
}
}
}