I'm trying to move to PB9 but a program I've got is giving me a pain.
Status:
The program uses a keyboard hook (Not a GLOBAL hook).
When run, either from the IDE or from a compiled EXE, the window opens below other windows, the Titlebar does not show the window as having focus and all typing still goes to whichever window had the KB focus before (like PBEdits).
Clicking the window to give it the focus and all is well, the program runs just fine. It's just not getting control (and focus) when launched. This failure is ONLY with PB9, with PB8 all works normally.
I can't post the whole program (its 9000+ lines) but I've finally managed to pare it down to a small sample which shows the failure. All it does is open a graphic window, accept keyboard chars and echo to the graphic window.
Here's the problem code. Yes it looks weird since I've cut/pasted it together from the main code and then deleted as much code as possible to reduce the 'noise'.
Status:
- Compiles and runs fine in PB8
- Compiles clean in PB9 after cleaning up a few new KWs (like TIX)
- In PB9 the program window does NOT get drawn topmost and does NOT have the focus.
The program uses a keyboard hook (Not a GLOBAL hook).
When run, either from the IDE or from a compiled EXE, the window opens below other windows, the Titlebar does not show the window as having focus and all typing still goes to whichever window had the KB focus before (like PBEdits).
Clicking the window to give it the focus and all is well, the program runs just fine. It's just not getting control (and focus) when launched. This failure is ONLY with PB9, with PB8 all works normally.
I can't post the whole program (its 9000+ lines) but I've finally managed to pare it down to a small sample which shows the failure. All it does is open a graphic window, accept keyboard chars and echo to the graphic window.
Here's the problem code. Yes it looks weird since I've cut/pasted it together from the main code and then deleted as much code as possible to reduce the 'noise'.
Code:
#COMPILE EXE #DIM ALL #INCLUDE "Win32Api.inc" UNION MsgDataLayout MsgWparam AS LONG MsgString AS STRING * 4 END UNION %IDC_SPFLiteWindow = 120 GLOBAL hWnd AS LONG GLOBAL hDC AS LONG GLOBAL FontName AS STRING GLOBAL FontPitch AS INTEGER GLOBAL FontHeight AS INTEGER GLOBAL FontWidth AS INTEGER GLOBAL ScrWidth AS INTEGER GLOBAL ScrHeight AS INTEGER GLOBAL ghKbrdHook AS LONG GLOBAL KeyChr AS STRING FUNCTION PBMAIN () AS LONG LOCAL x, y AS LONG, t AS STRING FontName = "Terminal": FontPitch = 12: ScrWidth = 60: ScrHeight = 30 '---------- Create a hidden basic screen based on the Profile screen sizes DIALOG NEW PIXELS, 0, "PB8PB9 Problem", 200, 200, 20, 20, _ %WS_CAPTION OR %WS_MINIMIZEBOX OR %WS_SYSMENU TO hWnd CONTROL ADD GRAPHIC, hWnd, %IDC_SPFLiteWindow,"", 0, 0, 20, 20 '---------- Get the Height/Width of the desired Font GRAPHIC ATTACH hWnd, %IDC_SPFLiteWindow ' Using the graphic window GRAPHIC FONT FontName, FontPitch, 0 ' Set the desired font GRAPHIC CHR SIZE TO FontWidth, FontHeight ' Get size of a character in that font '---------- Destroy the old window & re-create now in the new size for the new font DIALOG END hWnd, 0 ' Shut the current Dialog & Re-Open x = ScrWidth * FontWidth + 3: y = Scrheight * FontHeight + 3 ' Calc window in desired font size ' '------ The following statement in PB8 works fine, in PB9 window open up NOT ON TOP and without the Focus ' DIALOG NEW PIXELS, 0, "PB8PB9 Problem", 100, 100, x, y, %WS_CAPTION OR %WS_MINIMIZEBOX OR %WS_SYSMENU, TO hWnd CONTROL ADD GRAPHIC, hWnd, %IDC_SPFLiteWindow,"", 0, 0, x, y GRAPHIC ATTACH hWnd, %IDC_SPFLiteWindow ' Set as the default graphic area GRAPHIC CLEAR 0 ' Clear the background GRAPHIC FONT FontName, FontPitch, 0 SetWindowText(hWnd, "PB8PB9 Problem") ' Alter window title DIALOG SHOW MODAL hWnd CALL DlgCallback ' CONTROL SET FOCUS hWnd, %IDC_SPFLiteWindow END FUNCTION CALLBACK FUNCTION DlgCallback() '---------- MAIN DIALOG'S CALLBACK PROCEDURE LOCAL i, j AS INTEGER LOCAL Msg AS MsgDataLayout SELECT CASE AS LONG CBMSG CASE %WM_INITDIALOG ghKbrdHook = SetWindowsHookEx(%WH_KEYBOARD, CODEPTR(KeyBoardHook), _ 0, GetCurrentThreadId) CASE %WM_DESTROY ' Sent when the dialog is being destroyed UnhookWindowsHookEx ghKbrdHook ' Kill the Keyboard hook CASE %WM_USER ' KeyBoardHook is sending us a Key Msg.MsgWparam = CBWPARAM ' Put wParam into the UNION KeyChr = TRIM$(Msg.MsgString) ' Convert string into KeyChr IF LEN(KeyChr) = 0 THEN KeyChr = " " ' Don't TRIM away spaces CALL KeyBoard() ' Let Keyboard routine have a go END SELECT END FUNCTION FUNCTION KeyBoardHook(BYVAL iCode AS INTEGER, BYVAL wParam AS LONG, BYVAL lParam AS LONG) AS DWORD '---------- Examine all keyboard traffic DIM KeyStateArray(0 TO 255) AS BYTE LOCAL KeyCode AS INTEGER LOCAL ScanCode AS INTEGER LOCAL ScanCodeL AS LONG LOCAL Chars AS STRING * 2 LOCAL i AS LONG LOCAL KMsg AS MsgDataLayout IF iCode < 0 THEN FUNCTION = CallNextHookEx(ghKbrdHook, iCode, wParam, lParam) EXIT FUNCTION END IF CallNextHookEx(ghKbrdHook, iCode, wParam, lParam) IF iCode <> %HC_ACTION THEN EXIT FUNCTION ' Exit if not a Keyboard action KeyChr = "" ' Clear our ultimate answer KeyCode = wParam ' Get the keycode ScanCodeL = lparam ' Get the ScanCode SHIFT LEFT ScanCodeL, 8 ' SHIFT RIGHT ScanCodeL, 24 ' ScanCode = ScanCodeL ' IF KeyCode = 0 THEN EXIT FUNCTION ' Bail out if somehow nothing IF (lParam AND &H80000000) <> 0 THEN EXIT FUNCTION ' Key UP? Just exit '---------- Get flags set for special keys GetKeyboardState(BYVAL VARPTR(KeyStateArray(0))) ' Get all key states etc i = ToAsciiEx(KeyCode, ScanCode, BYREF KeyStateArray(0), _ BYVAL VARPTR(Chars), 0, GetKeyboardLayout(0)) IF i < 0 THEN ' Diaetric Dead key? FUNCTION = 1 ' Set RC = 1 EXIT FUNCTION ' Just Exit END IF IF i = 2 THEN ' If 2 then we had an unused dead key KMsg.MsgString = LEFT$(LEFT$(Chars,1)+" ", 4) ' Pass back the first key i = PostMessage(hWnd, %WM_USER, KMsg.MsgwParam, 0) i = 1: MID$(Chars, 1, 1) = MID$(Chars, 2, 1) ' Make it look like only one key now END IF IF i = 1 THEN ' We have an ASCII character IF KeyChr = "" THEN KeyChr = LEFT$(Chars,1) ' If still "" then it's a 'normal' alpha type key END IF IF LEN(KeyChr) > 0 THEN KMsg.MsgString = LEFT$(KeyChr+" ", 4) IF LEFT$(KeyChr,3) = "CHR" THEN KMsg.MsgString = MID$(KeyChr,4,1) + " " i = PostMessage(hWnd, %WM_USER, KMsg.MsgwParam, 0) FUNCTION = 1 ELSE FUNCTION = 0 END IF END FUNCTION SUB KeyBoard() '---------- Keyboard processor STATIC col AS LONG col = col + FontWidth GRAPHIC SET POS (col, 100) GRAPHIC PRINT KeyChr; END SUB
Comment