PDA

View Full Version : Problem with windows hotkeys



chronozphere
19-11-2006, 10:43 AM
Hi :)

I have a problem with the windows hotkeys.
When i press F10, my game freezes because F10 activates the menu bar and the app loses focus.
When i press Alt, the same thing happens. :(
I am sure there are more hotkeys, which do things i don't want.

What is the best way to disable these hotkeys?? :?

Delfi
19-11-2006, 01:31 PM
I had same problem, so i went and checked if alt key gave any special messages, and came up with this solution in message loop:




// wm_syskey messages are filtered to prevent app freeze and
// confuse player when he presses the ALT key. this also redirects
// system key codes into our key array and enables us to actually
// even capture these keypresses ( FYI alt key is vk_menu. )


WM_SYSKEYDOWN:
begin
ProcessKeyDown(wparam, lparam);
Result := 0;
end;
WM_SYSKEYUP:
begin
ProcessKeyUp(wparam, lparam);
Result := 0;
end;

chronozphere
19-11-2006, 05:26 PM
It doesn't compile :( ProcessKeyDown is an undeclared identifier.

in which unit is this it defined???

cronodragon
19-11-2006, 06:02 PM
It doesn't compile :( ProcessKeyDown is an undeclared identifier.

in which unit is this it defined???

I think you have to declare it yourself :P

BTW, I have a related questions. I hide the mouse cursor when I get a WM_SETFOCUS, but I want to show it again with WM_KILLFOCUS... but ShowCursor(True) doesn't seem to work when receiving that message, probably because the focus is already lost and ShowCursor() doesn't allow to tell which window handle I'm refering to. What can I do?

chronozphere
19-11-2006, 06:14 PM
Sorry but i dont know how i must declare it. :?
I do not recieve the input using messages. i use Directinput. so i dont know what those methods must do.

Just "Result := 0;" isn't enough to fix the problem. Something else must be done.

Delfi
19-11-2006, 06:28 PM
Sorry but i dont know how i must declare it. :?
I do not recieve the input using messages. i use Directinput. so i dont know what those methods must do.

Just "Result := 0;" isn't enough to fix the problem. Something else must be done.

The princip is same, just put them into a delphi-special-wm-handling-functions message function into the form object in the unit.

cronodragon
19-11-2006, 06:28 PM
I'm just getting out from those problems... DirectInput is not very compatible with the system input. :?

You could do it in 2 ways:

1. Capture messages in a normal VCL application, as suggested by Delfi, or

2. Make your own window processing loop in a formless application.

If you follow the first path, first learn about capturing and processing messages with a TForm:

http://www.informit.com/articles/article.asp?p=27217&seqNum=1&rl=1

If you follow the second path, read this tutorial about creating a formless app:

http://delphi.about.com/od/windowsshellapi/a/apicourse.htm

chronozphere
19-11-2006, 07:03 PM
It works.. i have written the following message handler:


function TBF_CustomEngine.WndProc(hWnd,Msg,wParam,lParam:In teger): integer;
begin
case Msg of
WM_ACTIVATEAPP : begin
fFocus := Boolean(wParam);
if fFocus then
begin
//has focus
//Log('>>>Application activated');
ShowCursor(false);
end else begin
//has no focus
//Log('>>>Application deactivated');
ShowCursor(true);
end;
end;

WM_TIMER: begin
//FPS update only when game has focus
fUpdateFPS := true;
end;

WM_CLOSE: begin
{WM_CLOSE quit's rendering loop
all resources and devices will be destroyed in
BF_Core's destructor wich is called when BF_Core.Run ended}
PostQuitMessage(0);
Exit;
end;
WM_SYSKEYDOWN: begin
//ProcessKeyDown(wparam, lparam);
Result := 0;
Exit;
end;
WM_SYSKEYUP: begin
//ProcessKeyUp(wparam, lparam);
Result := 0;
Exit;
end;
end;

Result := DefWindowProc(hWnd,Msg,wParam,lParam);
end;


I had to add the "exit;" statements because else the "defwindowProc" would be executed anyway. :)

Thanx for your help

cronodragon
19-11-2006, 07:09 PM
Is that WndProc() a class method? How do you declare it in the class to be called correctly? And how do you assign it to lpfnWndProc when creating the window class?

EDIT: Anyway, maybe it's a VCL event, so it doesn't apply to formless apps.

Delfi
19-11-2006, 10:01 PM
Is that WndProc() a class method? How do you declare it in the class to be called correctly? And how do you assign it to lpfnWndProc when creating the window class?

EDIT: Anyway, maybe it's a VCL event, so it doesn't apply to formless apps.

yup, vcl tricks here :)

something similar to this:


type
TForm1 = class(TForm)
procedure WMRecv(var Message: TMessage); message WM_RECV;

and the TForm1.WMRecv will be called when the vcl's message loop goes around and detects it.

jasonf
20-11-2006, 10:16 AM
Will this code work for Windows' Sticky Keys?

I'm using SDL Input and one of my principle controls is the [Shift] key. But, on WindowsXP, prolonged use of the [Shift] key makes windows think I want to use Sticky Keys which seriously messes with the game. I get my rocket tanks flying off the top of the screen (Thanks Microsoft! :evil: )

Will this code prevent that?

cronodragon
20-11-2006, 12:42 PM
No, I think it doesn't prevent the Sticky Keys, the user must disable them. I hope Vista doesn't bring more of those tricks :?

Delfi
20-11-2006, 03:42 PM
I hope Vista doesn't bring more of those tricks :?

Beware! There comes sticky cursor :P

chronozphere
24-11-2006, 01:46 PM
yup, vcl tricks here Smile

no VCL tricks... ;) I did the following:


{Window proc}

function WindowProc(hWnd,Msg,wParam,lParam:Integer):Integer ; stdcall;
begin
//Currentengine is a TBF_CustomEngine object.
//so i just pass on the messages to a member of the TBF_CustomEngine class

Result :=CurrentEngine.WndProc(hWnd,Msg,wParam,lParam);
end;

function TBF_CustomEngine.WndProc(hWnd,Msg,wParam,lParam:In teger): integer;
begin
case Msg of
WM_ACTIVATEAPP : begin
fFocus := Boolean(wParam);
if fFocus then
begin
//has focus
Log('>>>Application activated');
ShowCursor(false);
end else begin
//has no focus
Log('>>>Application deactivated');
ShowCursor(true);
end;
end;

WM_TIMER: begin
//FPS update only when game has focus
fUpdateFPS := true;
end;

WM_CLOSE: begin
{WM_CLOSE quit's rendering loop
all resources and devices will be destroyed in
BF_Core's destructor wich is called when BF_Core.Run ended}
PostQuitMessage(0);
Exit;
end;
WM_SYSKEYDOWN: begin
//ProcessKeyDown(wparam, lparam);
Result := 0;
Exit;
end;
WM_SYSKEYUP: begin
//ProcessKeyUp(wparam, lparam);
Result := 0;
Exit;
end;
end;

Result := DefWindowProc(hWnd,Msg,wParam,lParam);
end;

constructor TBF_CustomEngine.Create;
begin
inherited Create;

fEngine := Self;
fParent := Self;
.....

//Initalize the application
wClass.lpszClassName:= 'CN';
wClass.lpfnWndProc := @WindowProc; //assign the windowproc function

.....

//create window
fHwnd := CreateWindow(wClass.lpszClassName,'bitFIST 3D',
WS_OVERLAPPEDWINDOW or WS_VISIBLE,
100,100,640,480,0,0,hInstance,nil);
end;

cronodragon
24-11-2006, 01:56 PM
Ok, I did the same but using a heap of windowses. 8)