Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WinAPI MoveWindow function not working for some windows

I want to resize and/or move some external windows from my application, mainly the On-Screen keyboardwindow. Here is the code:

     [DllImport("user32.dll", SetLastError = true)]
    internal static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);

    [DllImport("user32.dll", EntryPoint = "SetWindowPos")]
    public static extern IntPtr SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int x, int Y, int cx, int cy, int wFlags);


    //assorted constants needed
    public static uint MF_BYPOSITION = 0x400;
    public static uint MF_REMOVE = 0x1000;
    public static int GWL_STYLE = -16;
    public static int WS_CHILD = 0x40000000; //child window
    public static int WS_BORDER = 0x00800000; //window with border
    public static int WS_DLGFRAME = 0x00400000; //window with double border but no title
    public static int WS_CAPTION = WS_BORDER | WS_DLGFRAME; //window with a title bar 
    public static int WS_SYSMENU = 0x00080000; //window menu  

    public const byte KEYEVENTF_EXTENDEDKEY = 0x0001; //Key down flag
    public const byte KEYEVENTF_KEYUP = 0x0002; //Key up flag
    public const byte VK_RCONTROL = 0xA3; //Top Control key code
    public const byte VK_CONTROL = 0x80; //Left Control key code

    const short SWP_NOMOVE = 0X2;
    const short SWP_NOSIZE = 1;
    const short SWP_NOZORDER = 0X4;
    const int SWP_SHOWWINDOW = 0x0040;

    #endregion

    public static void WindowsReStyle()
    {

        Process p = Process.GetProcesses().Where(d => d.ProcessName.Contains("osk")).DefaultIfEmpty(null).FirstOrDefault();

        IntPtr hWndOSK = p.MainWindowHandle;

        string title = p != null ? p.MainWindowTitle : "";

        bool b = MoveWindow(hWndOSK, 600, 600, 600, 600, true);

        int i = System.Runtime.InteropServices.Marshal.GetLastWin32Error();

        SetWindowPos(hWndOSK, 0, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_SHOWWINDOW);

        i = System.Runtime.InteropServices.Marshal.GetLastWin32Error();
    }

But the problem is that the IntPtr handle is found correctly, but the window is neither moved nor resized. I tried bot MoveWindow and SetWindowPos functions, and they does not work.

GetLastWin32Error() 

function returns sometimes code

1400 (wrong hanlde), 

sometimes

5 (Access denied).

How can I solve that?

like image 271
v.chjen Avatar asked Jul 17 '14 06:07

v.chjen


1 Answers

The on screen keyboard runs at a high integrity level. This means that you need your process also to run at that integrity level. The first thing to do is to execute your program as admin. That will run your process at a high integrity level.

Of course, you are unlikely to find the prospect of running your app elevated, and so presenting its users with UAC dialogs, very appealing. But that's just a consequence of the system design.

Do note that your error handling is incorrect. Only check the error code if the API functions fails. Which means checking the return value of the function. And your p/invoke for SetWindowPos is flawed. It fails to set SetLastError. These details really do matter and you must take great care. The compiler cannot check interop code for correctness.

like image 190
David Heffernan Avatar answered Nov 22 '22 02:11

David Heffernan