Of course there are plenty of such a soft available on the Internet (however it is all shareware), but as I already have said I had a free time at my job and strong interest to low-level programming (it is really low-level comparing to my everyday tasks).
Here is requirements for utility I need:
- It must turn off the display when launched
- It must turn it on back when ESC key is pressed
Very simple isn't it?
I have no problems with turning display on/off:
//Turn off
SendMessage(HWND_TOPMOST, WM_SYSCOMMAND, SC_MONITORPOWER, 2);
//Turn on
SendMessage(HWND_TOPMOST, WM_SYSCOMMAND, SC_MONITORPOWER, -1);
Btw, as the window handle you can pass any valid handle
The only problem I had was Windows hooks. Some experience gathered
- If you want to register global hook you MUST define its function in separate DLL
- When registering global hook (registration code can be in the hook DLL or in the calling process, it doesn't matter) use the following code:
SetWindowsHookEx(WH_KEYBOARD, HookFunction, hDLLInstance, 0);- If you want to store any data in the DLL process namespace think if it must be shared between all your-DLL-and-process connections - because Windows allocates separate memory space for DLL data for each process that uses this DLL. For example, in my case, as DLL contained system-wide keyboard hook, it will have separate space
for data for each process where hook event occured. But, I need to store HWND variable for my utility hidden window - to send WM_DISPOSE event to it when user press ESC key (it is the best way I know to close application. May be there are better ways, simply I don't know them). So the solution will be to store this HWND value in shared DLL memory space - in this case it doesn't matter which process will "execute" the hook - HWND value will be the same for all the DLL instances.
Here is code example how to define shared-variable section:
//Will store main window handle at shared DLL memory space
#pragma data_seg(".SHARED")
HWND hWnd = NULL;
//hook management
HHOOK hhookKeyboardHook;
#pragma data_seg()
#pragma comment(linker, "/section:.SHARED,rws")
And here is the hook function code:
LRESULT __stdcall HookFunction(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode < 0){ // do not process message
return CallNextHookEx((HHOOK)HookFunction, nCode, wParam, lParam);
} else if (VK_ESCAPE == wParam){
//Turn on the monitor
SendMessage(HWND_TOPMOST, WM_SYSCOMMAND, SC_MONITORPOWER, -1);
//Release hook
if(NULL != hhookKeyboardHook ){
UnhookWindowsHookEx(hhookKeyboardHook );
}
//Send message to close application
SendMessage(hWnd, WM_DESTROY, 0, 0);
}
//calling next hook which may exist
return CallNextHookEx((HHOOK)HookFunction, nCode, wParam, lParam);
}
And code which sets the hook:
__declspec(dllexport) void __stdcall SetHook(HWND windowHandle){
hWnd = windowHandle;
SendMessage(HWND_TOPMOST, WM_SYSCOMMAND, SC_MONITORPOWER, 2);
SetWindowsHookEx(WH_KEYBOARD, HookFunction, hInst, 0);
}
Both functions are located at separate DLL, SetHook is marked as __declspec(dllexport) to be able to dynamically call it from dynamically loaded DLL library. I used Microsoft Visual Studio 2003 to work on this problem.
1 comment:
Well said.
Post a Comment