Pelles C forum

C language => Windows questions => Topic started by: czerny on January 16, 2015, 04:23:02 PM

Title: Reset NumLock etc.
Post by: czerny on January 16, 2015, 04:23:02 PM
Hallo!

It seems as if I have another silly question.

I want to show a busy period by switching the three keyboard leds sequential on and off.

To restore the state of the three keys, I first save it.

But the restauration doesn't work. What I am doing wrong here?
Title: Re: Reset NumLock etc.
Post by: frankie on January 16, 2015, 07:23:27 PM
Code: [Select]
static void Main_OnPaint(HWND hwnd)
{
PAINTSTRUCT ps;
RECT rc;

BeginPaint(hwnd, &ps);
GetClientRect(hwnd, &rc);
DrawText(ps.hdc, _T(" Start"), -1, &rc, DT_SINGLELINE | DT_LEFT | DT_VCENTER);
BusyStart(hwnd, 100);
Sleep(10000);
BusyStop(hwnd);
DrawText(ps.hdc, _T("Stop "), -1, &rc, DT_SINGLELINE | DT_RIGHT | DT_VCENTER);
EndPaint(hwnd, &ps);
}
:o The message loop stocked for 10 seconds?  :o
Check the attachment.
Title: Re: Reset NumLock etc.
Post by: czerny on January 17, 2015, 01:10:34 AM
I know that the message loop was blocked. That's why I don't want to use the SetTimer api. The MMTimer do not depend on the message loop.
Title: Re: Reset NumLock etc.
Post by: frankie on January 17, 2015, 03:40:22 PM
Yes, but the keyboard status is not updated in the messages queue so you read again the last state and the final setting is wrong.
Allowing the message loop to run the sample works.
Title: Re: Reset NumLock etc.
Post by: czerny on January 17, 2015, 09:32:08 PM
Yes, but the keyboard status is not updated in the messages queue so you read again the last state and the final setting is wrong.
How does GetKeyboardState depend on the message queue? And why is it working ok all the time while rotating the leds?
Title: Re: Reset NumLock etc.
Post by: frankie on January 17, 2015, 10:43:47 PM
To be honest I've not investigated so much because I've no much time, but anyway from MSDN description of GetKeyboardState  (http://msdn.microsoft.com/en-us/library/windows/desktop/ms646299%28v=vs.85%29.aspx) in remark section:
Quote
An application can call this function to retrieve the current status of all the virtual keys. The status changes as a thread removes keyboard messages from its message queue. The status does not change as keyboard messages are posted to the thread's message queue, nor does it change as keyboard messages are posted to or retrieved from message queues of other threads.
.
Maybe you simply blindly toggle the status and it seems to work (if the case they should change at half the frequency of timer).
Title: Re: Reset NumLock etc.
Post by: czerny on January 18, 2015, 02:49:17 PM
There is something wrong with SetState himself:
Code: [Select]
#include <windows.h>
#include <stdio.h>

void SetState(BYTE bVk, BYTE bScan, BOOL bState)
{
BYTE keyState[256];
 
GetKeyboardState((LPBYTE)&keyState);
if ((bState && !(keyState[bVk] & 1)) || (!bState && (keyState[bVk] & 1)))
{
keybd_event(bVk, bScan, KEYEVENTF_EXTENDEDKEY | 0, 0);
keybd_event(bVk, bScan, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
}
}
int main(int argc, char **argv)
{
SetState(VK_SCROLL, 0x46, TRUE);
Sleep(2000);
SetState(VK_SCROLL, 0x46, FALSE);

return 0;
}
led is on.
Title: Re: Reset NumLock etc.
Post by: jj2007 on January 18, 2015, 03:10:42 PM
In my editor, I have disabled the NumLock key by handling the keydown message as follows (pseudocode):

  .if uMsg==WM_KEYDOWN && wParam==VK_NUMLOCK
      invoke GetKeyState, ebx
      test al, 1
      .if Zero?
         invoke keybd_event, ebx, 0, KEYEVENTF_KEYUP, 0     ; first, release the key
         invoke Sleep, 1
         invoke keybd_event, ebx, 0, 0, 0            ; second, trigger a second keypress to toggle
      .endif

The logic is as follows:
- numlock is being pressed by user
- we catch the keydown message
- we insert a keyup message for the same key
- then we insert a keydown message
- and Windows completes the whole cycle by handling the keyup message.

This cheats the message queue by inserting keyup and keydown:
keydown  ; windows
keyup  ; handler
keydown  ; handler
keyup  ; windows

Result: the key can't be activated.
Title: Re: Reset NumLock etc.
Post by: frankie on January 18, 2015, 04:04:15 PM
The problem is again the missing message loop, the static array returned by GetKeyboardState is updated during messages processing when a key event message is retreived!
Try using the asynchronus version of state as in the emended example below.
It works for your simple sample, but I've not tested it deeply.
Code: [Select]
void SetState(BYTE bVk, BYTE bScan, BOOL bState)
{
//BYTE keyState[256];
 
//GetKeyboardState((LPBYTE)&keyState);
SHORT State = GetAsyncKeyState(bVk);
//if ((bState && !(keyState[bVk] & 1)) || (!bState && (keyState[bVk] & 1)))
if ((bState && !(State & 1)) || (!bState && (State & 1)))
{
keybd_event(bVk, bScan, KEYEVENTF_EXTENDEDKEY | 0, 0);
keybd_event(bVk, bScan, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
}
}
Title: Re: Reset NumLock etc.
Post by: aardvajk on January 18, 2015, 04:59:46 PM
Quote
I want to show a busy period by switching the three keyboard leds sequential on and off.
Use a progress bar and/or the hourglass cursor, it's what they're there for. They also don't interfere with doing other things (i.e. typing in other programs) while your program's busy.

In my editor, I have disabled the NumLock key by handling the keydown message as follows (pseudocode):
Result: the key can't be activated.
Your editor would be better served if you implemented Page Down, Page Up, Home and End rather than just stopping me and I'm sure plenty of other laptop users for whom NumLock disables and/or changes the location of those keys, from being able to use them.
Title: Re: Reset NumLock etc.
Post by: jj2007 on January 18, 2015, 05:10:30 PM
In my editor, I have disabled the NumLock key by handling the keydown message as follows (pseudocode):
Result: the key can't be activated.
Your editor would be better served if you implemented Page Down, Page Up, Home and End rather than just stopping me and I'm sure plenty of other laptop users for whom NumLock disables and/or changes the location of those keys, from being able to use them.

My notebook does have Page Down, Page Up, Home and End right above the numpad. It's a major nuisance that some very frequently used keys, namely Backspace, Delete and Home, are placed in the direct neighbourhood of NumLock. You want to type "9" and find yourself one page down in the middle of nowhere, just because before you hit by accident that bloody NumLock key. Equally annoying are Insert and CapsLock - keys that are extremely rarely used but if hit by accident (a dozen times a day at least) will cause you to write nonsense. But of course, I could make that feature optional. Actually, thanks for your critique, I just realised that there is no numpad on the other notebook ;-)
Title: Re: Reset NumLock etc.
Post by: czerny on January 18, 2015, 09:13:14 PM
Use a progress bar and/or the hourglass cursor, it's what they're there for.
I have learned, that only going new -- maybe strange -- ways gives new knowledge.