Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to enable tab and arrow keys using python win32gui

I've created several buttons (windows) in a main window, but tab and arrow keys are not working. My research revealed that for C++, the use of IsDialogMessage in the message pump creates a bypass of TranslateMessage/DispatchMessage as follows to allow this functionality:

while(GetMessage(&Msg, NULL, 0, 0))
{
    if(!IsDialogMessage(g_hToolbar, &Msg))
    {
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
    }
}

However, I'm using python and the win32gui module to CreateWindows and I can't figure out how to bypass the normal message capture to allow natural handling of the keyboard. My code is similar to this:

from win32gui import *
from win32con import *

window_class = WNDCLASS()
hinst = window_class.hInstance = GetModuleHandle(None)
window_class.lpszClassName = 'ClassName'
window_class.style = CS_VREDRAW | CS_HREDRAW
window_class.hCursor = LoadCursor(0, IDC_ARROW)
window_class.hbrBackground = COLOR_WINDOW
window_class.lpfnWndProc = {}
classAtom = RegisterClass(window_class)

hwnd = CreateWindow(classAtom, "", WS_VISIBLE | WS_OVERLAPPED | WS_CAPTION
                    | WS_SYSMENU | WS_MINIMIZEBOX | WS_EX_TOPMOST | WS_CLIPSIBLINGS,
                    0, 0, 140, 100, 0,  0, GetModuleHandle(None), None)
btn1_hwnd = CreateWindow("Button", "btn 1", WS_GROUP | WS_TABSTOP | WS_VISIBLE
                         | WS_CHILD | BS_DEFPUSHBUTTON | WS_CLIPSIBLINGS,
                         10, 10, 100, 20, hwnd, 0, GetModuleHandle(None), None)
btn2_hwnd = CreateWindow("Button", "btn 2", WS_GROUP | WS_TABSTOP | WS_VISIBLE
                         | WS_CHILD | BS_DEFPUSHBUTTON | WS_CLIPSIBLINGS,
                         10, 40, 100, 20, hwnd, 0, GetModuleHandle(None), None)

UpdateWindow(hwnd)
PumpMessages()

EDIT: With this code, a window with two buttons is created, but it is not possible to move focus from one to the other, although they both have WS_TABSTOP flag.

According to MSDN IsDialogMessage specification, the C++ snippet above is the solution.

When IsDialogMessage processes a message, it checks for keyboard messages and converts them into selections for the corresponding dialog box. For example, the TAB key, when pressed, selects the next control or group of controls, and the DOWN ARROW key, when pressed, selects the next control in a group.

Because the IsDialogMessage function performs all necessary translating and dispatching of messages, a message processed by IsDialogMessage must not be passed to the TranslateMessage or DispatchMessage function.

So, basically, the question is: can IsDialogMessage be used from Python's win2gui, or is there some workaround?

like image 945
mjpsr11 Avatar asked Dec 13 '15 23:12

mjpsr11


1 Answers

I have found an example of CreateDialogIndirect usage on programcreek.com which creates a window similar to the one from the question, with tabs working. Here it is, slightly modified:

import win32con
import win32gui
import win32api

parent_hwnd = None
msgs = {}
style=win32con.WS_BORDER|win32con.WS_VISIBLE|win32con.WS_CAPTION|win32con.WS_SYSMENU  ## |win32con.DS_SYSMODAL
h=win32gui.CreateDialogIndirect(
    win32api.GetModuleHandle(None),
    [['One ugly dialog box !',(100,100,200,100),style,0],
     ['Button','Create', win32con.IDOK, (10,10,30,20),win32con.WS_VISIBLE|win32con.WS_TABSTOP|win32con.BS_HOLLOW|win32con.BS_DEFPUSHBUTTON],
     ['Button','Never mind', win32con.IDCANCEL, (45,10,50,20),win32con.WS_VISIBLE|win32con.WS_TABSTOP|win32con.BS_HOLLOW],
     ['Static','Desktop name:',71,(10,40,70,10),win32con.WS_VISIBLE],
     ['Edit','',72,(75,40,90,10),win32con.WS_VISIBLE]],
    parent_hwnd, msgs)

win32gui.EnableWindow(h,True)
hcontrol = win32gui.GetDlgItem(h,72)
win32gui.EnableWindow(hcontrol,True)
win32gui.SetFocus(hcontrol)
win32gui.PumpMessages()
like image 190
zvone Avatar answered Oct 04 '22 03:10

zvone