I knew that the last 30 years of programming hadn't gone to waste!
Guino,
I once reported a problem with handling the SCROLLLOCK key and passing it to Milkdrop. I think I even *bumped* the thread here earlier today. Anyway, I broke down and wrote a windows program to test some theories and figured out what the problem was, and more importantly, the solution which I will share!
The problem: Milkdrop uses the ScrollLock key to lock/unlock the current visualization on the screen. This isn't a problem if you are only running WinAmp and have a Milkdrop window open and it has focus. But when you embed it in anything and try to pass the keystroke to it, it fails the second time you try again.
In looking at the source to Milkdrop I learned a couple things.
1. that trying to use a PostMessage with a single character is handled normally:
Code:
PostMessage(WinHandle, WM_CHAR, Ord('H'), 0);// Send a 'H' to the application handle
2. That you need to send a SCROLLLOCK keypress differently:
Code:
PostMessage(WinHandle, WM_KEYDOWN, VK_SCROLL,0); // and tell Milkdrop about it...
3. That when Milkdrop received the WM_KEYDOWN message and processes it, it is told to go LOOK at the keyboard status light for ScrollLock and use whatever value it finds.
4. When Milkdrom reads the keyboard status from Windows, it finds that it has not changed! So #2 above failed in spectacular fashion.
THE SOLUTION!
To tell Milkdrop to read the ScrollLock keyboard status is not enough. You first have to tell Windows to change the bits and either turn on or turn off the status light.
So #2 needs to look like this:
Code:
SetLedState(ktScrollLock, ScrollLockState); // Set ScrollLock to next saved state
ScrollLockState := not ScrollLockState; // flip the state for next time
PostMessage(WinHandle, WM_KEYDOWN, VK_SCROLL,0); // and tell Milkdrop about it...
The key is the first line. And here is the procedure I used to do this:
Code:
type
TKeyType = (ktCapsLock, ktNumLock, ktScrollLock);
procedure SetLedState(KeyCode: TKeyType; bOn: Boolean);
var
KBState: TKeyboardState;
bCode: Byte;
begin
case KeyCode of
ktScrollLock: bCode := VK_SCROLL;
ktCapsLock: bCode := VK_CAPITAL;
ktNumLock: bCode := VK_NUMLOCK;
end;
GetKeyboardState(KBState);
if (Win32Platform = VER_PLATFORM_WIN32_NT) then
begin
if Boolean(KBState[bCode]) <> bOn then
begin
keybd_event(bCode,MapVirtualKey(bCode, 0),KEYEVENTF_EXTENDEDKEY,0);
keybd_event(bCode,MapVirtualKey(bCode, 0),KEYEVENTF_EXTENDEDKEY or KEYEVENTF_KEYUP,0);
end;
end
else
begin
KBState[bCode] := Ord(bOn);
SetKeyboardState(KBState);
end;
end;
This was written in Codegear/Borland Delphi 2007 but should be convertable to any other language. You do have to get the handle to the Milkdrop window to be able to tell it to change. I used this call to find it:
Code:
WinHandle := FindWIndow(nil, "milkdrop" );
Anyway, I turned this into a small program that sits in the tasktray and call it in a skin with:
Code:
B08,2,6,81,63,"ACTIVATE;MilkDropHelper||SENDKEY;{S}" ,"ScrollLock"
Hope this helps RoadRunner in that when you change the SENDKEY;{SCROLLLOCK} that you also flip the keyboard bits at the same time. Then I wouldn't need my helper app.
Cheers!
John
Bookmarks