How to get virtkey value for WM_KEYDOWN in WS_CHILD? - c

I want to know the value of virtual key pressed when a child window(like 'edit' or 'button') has focus.
How to do that?

Well one way is to use
WNDPROC g_OldProc;
LRESULT CALLBACK MyEditWindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
if ( uMsg == WM_KEYDOWN )
{
// Handle key down.
}
return g_OldProc( hwnd, uMsg, wParam, lParam );
}
then at some opportune moment
g_OldProc = (WNDPROC)GetWindowLongPtr( hEdit, GWLP_WNDPROC );
SetWindowLongPtr( hEdit, GWLP_WNDPROC, (LONG_PTR)MyEditWindowProc );
This will replace the window procedure of the hEdit control with your own window procedure that, in turn, calls the original window procedure.

You could catch them at the level of the message loop (before calling DispatchMessage). Nasty but will work.

You could use the GetKeyState Win32 API from within a WM_SETFOCUS handler.

Related

Menus in WinAPI: Do I use LPARAM or WPARAM for WM_COMMAND?

I've recently started teaching myself WinAPI, so bear with me here.
Compiler: TDM-GCC 4.9.2
OS: Windows 8.1 64-bit
I've recently learned how to create menus using resources. In regards to that, I've noticed something odd about handling the WM_COMMAND message for menus. The MSDN documentation tells me that if I want to handle a message sent from a menu, the command item ID can be found in the low word of WPARAM; so I assumed that the code in my window procedure would look like this:
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, LPARAM lParam, WPARAM wParam)
{
switch (msg)
{
case WM_COMMAND:
switch (LOWORD(wParam)) //<--
{
case /*IDs go here*/:
break;
}
break;
//...
}
return 0;
}
However, I noticed that the command items in the menu weren't working. After some debugging, I figured out that wParam was always 0 and my IDs were actually in lParam! I made the quick change to the following code:
switch (lParam)
{
case /*IDs go here*/:
break;
}
And it works!
My question: why?
How come the documentation says it's in wParam when for me it's in lParam?
Also, here are my resource.rc and resource.h files in case it helps:
"resource.h":
#define IDR_MYMENU 101
//These are appearing in LPARAM instead of WPARAM
#define ID_FILE_EXIT 9001
#define ID_STUFF_GO 9002
"resource.rc":
#include "resource.h"
IDR_MYMENU MENU
BEGIN
POPUP "&File"
BEGIN
MENUITEM "E&xit", ID_FILE_EXIT
END
POPUP "&Stuff"
BEGIN
MENUITEM "&Go", ID_STUFF_GO
MENUITEM "G&o somewhere else", 0, GRAYED
END
END
Edit 7/23/15:
SOLVED. My window procedure had the wrong signature. Can't believe it was something so trivial! Thanks, cremno!
The WPARAM and LPARAM parameter are not in the correct order in your code:
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, LPARAM lParam, WPARAM wParam)
From the WindowProc callback function MSDN documentation:
LRESULT CALLBACK WindowProc(
_In_ HWND hwnd,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
Just swap them to fix your code:
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
Your WM_COMMAND message handling should check the high-order WORD of wParam first. Because this value tells you if it is a Menu, Accelerator or child control which is sending the message.
swtich(msg)
{
case WM_COMMAND:
{
switch(HIWORD(wParam))
{
case 0: // Menu
{
// Check LOWORD(wParam) here
break;
}
}
return 0;
}
See the table on the MSDN documentation: WM_COMMAND message

How do I disable the 'Close Window' option in the taskbar?

How to write a C Code in order to disable the 'Close Window' option in the taskbar?
Compiler: GCC-mingw32
Which API Function should I use?
Thanks.
Make the window's message dispatcher process the message WM_SYSCOMMAND and filter it out if the message's wParam is SC_CLOSE.
Let WndProc be the windows message handler then the code to do might look like this:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
...
switch (message)
{
case WM_SYSCOMMAND:
if (wParam == SC_CLOSE);
break;
return DefWindowProc(hWnd, message, wParam, lParam);
case ...
}
return 0;
}
This does not remove the "close"-menu item from the application's jump-list (its taskbar's local menu), but disables its functionality.

Trying Subclassing on Console

I want to trap keyboard messages in a console application, so I tried this:
HWND GetConsoleHwnd(void)
{
#define SIZEBUF 1024
char szBuffer[SIZEBUF];
GetConsoleTitle(szBuffer, SIZEBUF);
#undef SIZEBUF
return FindWindow(NULL, szBuffer);
}
LRESULT CALLBACK ConsoleProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_KEYDOWN:
switch (wParam)
{
//VK Cases
}
break;
}
return CallWindowProc(OldConsoleProc, hwnd, msg, wParam, lParam);
}
this in main:
HWND hwndConsole = GetConsoleHwnd();
OldConsoleProc = (WNDPROC) SetWindowLong(hwndConsole, GWL_WNDPROC,
ConsoleProc);
and this Global Var: WNDPROC OldConsoleProc;
but it doesnt work, what I am doing wrong?
You can't subclass a window of another process this way. You can do it with hooks but I wouldn't recommend trying this on console window. ReadConsoleInput is low-level enough, and it's as far as you can get without ugly nonportable hacks (I'm not even sure there are some events reaching WndProc when the console window is full screen).

Use WH_MOUSE globally without DLL

I have a code to display a part of screen when mouse moves. But the WH_MOUSE doesn't work. I need to change GetModuleHandle(0), 0 to hInst, GetCurrentThreadId().
But then the application will work only when the mouse is over the application itself.
I want it global and I tried WH_MOUSE_LL, it is slower then WH_MOUSE.
Is that possible to use WH_MOUSE globally without DLL?
void SetHook()
{
gMouseHook = SetWindowsHookEx(WH_MOUSE, MouseProc, GetModuleHandle(0), 0);
}
//================================================================================
// Mouse Hook
static LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode < 0) {
return CallNextHookEx(gMouseHook, nCode, wParam, lParam);
}
if (wParam == WM_MOUSEMOVE) {
MOUSEHOOKSTRUCT *mouseInfo = (MOUSEHOOKSTRUCT*)lParam;
int x = mouseInfo->pt.x;
int y = mouseInfo->pt.y;
PrintScreen(x, y);
}
return CallNextHookEx(gMouseHook, nCode, wParam, lParam);
}
Is that possible to use WH_MOUSE globally without DLL?
No, the hook procedure needs to be in a DLL so that it can be injected into other processes.
I tried WH_MOUSE_LL, it is slower then WH_MOUSE.
That probably means your hook procedure is slow.

Why doesn't SAPI's ISpNotifySource::SetNotifyWindowMessage() send the notification to my WndProc()?

I'm using WinForms, and I'm trying to get SetNotifyWindowMessage() to send a message to the WndProc, but it does not do so.
The function call:
HRESULT initSAPI(HWND hWnd)
{
...
if(FAILED( g_cpRecoCtxt->SetNotifyWindowMessage( hWnd, WM_RECOEVENT, 0, 0 )))
MessageBoxW(hWnd, L"Error sending window message", L"SAPI Initialization Error", 0);
...
}
The WndProc:
LRESULT WndProc (HWND hWnd, UINT message, WPARAM wparam, LPARAM lparam)
{
case WM_RECOEVENT:
ProcessRecoEvent(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
Note: initSAPI() is called on a mouse click event.
Have you called ISpRecoContext::SetInterest as well? SetNotifyWindowMessage specifies what to do when an event occurs, but doesn't specify what events to listen for.

Resources