Where are the rest of the TMessage missing params? - winapi

The VCL TMessage class provides the Message, WParam and LParam members, but a window message has more members:
typedef struct tagMSG {
HWND hwnd;
UINT message;
WPARAM wParam;
LPARAM lParam;
DWORD time;
POINT pt;
DWORD lPrivate;
} MSG, *PMSG, *NPMSG, *LPMSG;
Where are the hwnd, time, pt and lPrivate members? I'm in specially need of the time parameter.
Is there a way to access the original message that TMessage is constructed from (or any other means to get the time parameter)?
I'm handling my messages in TComponent::WndProc(Winapi::Messages::TMessage &Message).

Where are the hwnd, time, pt and lPrivate members?
There aren't any such members in TMessage.
MSG is the structure that the Win32 API uses in a message loop to retrieve messages from a message queue, via the GetMessage() and PeekMessage() functions, prior to dispatching them to window procedures via DispatchMessage(). The time, pt, and lPrivate values are not delivered to a window procedure, however a window procedure can retrieve the time and pt values via the GetMessageTime() and GetMessagePos() functions, respectively (the lPrivate value is not accessible).
TMessage is the structure that the VCL uses in window procedures that are created by the RTL's MakeObjectInstance() function. This function allows classes, like the VCL's TWinControl and TTimer, to use non-static virtual WndProc() methods as Win32 window procedures.
In a standard Win32 window procedure, there are only 4 parameters available - hWnd, uMsg, wParam and lParam. An RTL-based window procedure ignores the hWnd (as it already knows exactly which object method to call), copies the uMsg, wParam and lParam values into a TMessage, calls the target WndProc() method passing it the TMessage, and then returns the TMessage::Result value back to the OS.
I'm in specially need of the time parameter. Is there a way to access the original message that TMessage is constructed from (or any other means to get the time parameter)?
If the message comes from the message queue of the thread that is calling your WndProc(), you can use the Win32 API GetMessageTime() function. Or, you can use the Win32 API SetWindowsHookEx() function to install a WH_GETMESSAGE hook into the thread's message queue.
If your component's WndProc() is called in the main UI thread specifically, you can alternatively use the VCL's TApplication::OnMessage or TApplicationEvents::OnMessage events, which receive a copy of the original MSG structure. Your component can use a private TApplicationEvents object to hook the OnMessage event.
However, a window procedure can receive both queued messages and non-queued messages, so if the message does not come from the calling thread's message queue at all, then there is simply no time (or pt) value available to retrieve for it, as non-queued messages do not go through the MSG structure to begin with.
I'm handling my messages in TComponent::WndProc(Winapi::Messages::TMessage &Message).
TComponent does not have a WndProc() method. Perhaps you are thinking of TWinControl::WndProc() instead?

Related

SendMessage - strange return values

I have an application which uses a three helper threads to read from a database (3 different tables, ~160,000 rows in total), create objects from those rows, then add the objects to one of two lists, depending on what type of object was created. The helper threads add objects to the list through a SendMessage call so that the main thread is the only object adding/removing to/from the list.
The odd thing is that SendMessage doesn't always succeed, I'll frequently get these two errors ERROR_ALREADY_EXISTS (183) and ERROR_TRUSTED_DOMAIN_FAILURE (1788). The function that SendMessage calls just adds an object to the list, and this function always returns success (0). There's no creating files (as ERROR_ALREADY_EXISTS seems to suggest) and there's no network calls so I'm not sure why I'm getting ERROR_TRUSTED_DOMAIN_FAILURE errors.
Any ideas on what might be causing these errors or any way to debug these errors?
As a note, before it was SendMessage I was using PostMessage and would get lots of ERROR_NOT_ENOUGH_QUOTA errors; SendMessage makes the utility work a lot better.
SendMessage() returns the result of the message that is sent. It is up to the message handler to decide what value is actually returned by SendMessage() to the sending code. GetLastError() is only meaningful if SendMessage() itself fails, and you have to use SetLastError() to detect that, eg:
SetLastError(0);
LRESULT res = SendMessage(...);
if ((res == 0) && (GetLastError() != 0))
{
// send failed, for example GetLastError()=ERROR_ACCESS_DENIED if UIPI blocked the message ...
}
else
{
// send succeeded, res is whatever value the message handler returned ...
}
This only works reliably if the target HWND is owned by a different thread than the one that is calling SendMessage(). GetLastError() cannot be influenced across thread boundaries. Any call to SetLastError() within the message handler affects the error code of the HWND's owning thread, not the error code of the sending thread.
However, if the target HWND is owned by the same thread that is calling SendMessage(), and the message handler happens to call SetLastError() (directly, or indirectly via a failed API call) to set a non-zero error code, and happens to return 0 as its result value for SendMessage() to return to the sender, then the only way I can think of for the sender to differentiate whether the error code returned by GetLastError() was set by SendMessage() itself on failure, or set by the message handler, is to use a thread-locale message hook via SetWindowsHookEx() to detect whether the message handler was actually called or not (the only condition I can think of for that happening is if the target HWND is invalid so SendMessage() cannot find its window procedure).
You can use GetWindowThreadProcessId() and GetCurrentThreadId() to check if the target HWND is owned by the calling thread or not.

How windows manages to send messages with more than two parameters?

Studying about message-handling in MFC, I've found that:
A message comes with 2 parameters that give you more information about the event. Each parameter is a 32-bit value: lParam and wParam.
So when I created a user-defined message wwith no parameters, I sent it with the code:
pParentOfClass ->SendMessage(WM_RECTANGLECHANGED,0,0);
but just to be curious, how windows manages to send messages with more than two parameter like WM_SIZE.
As it was already quickly stated in the comment by Roger Rowland, multiple parameters are often packed into the low and/or high order of the LPARAM and WPARAM parameters when using messages.
What you probably mean by more parameters than two, is the fact that MFC has it's own event handler wrappers which already took the necessary information from the LPARAM and WPARAM parameters and forwarded it to it's own event handler implementations, which of course can have as many parameters as desired.
Example with WM_SIZE:
Originally, the WM_SIZE message is sent with LPARAM containing some flags and WPARAM containing width and height (through packing into low and high order).
Now MFC receives that message, gets all info it thinks is necessary for the user and calls its own event handler:
afx_msg void OnSize(
UINT nType,
int cx,
int cy
);
That's basically it.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms632646%28v=vs.85%29.aspx
http://msdn.microsoft.com/en-us/library/h464d4f3%28v=vs.90%29.aspx
Take a look at MAKEWPARAM (http://msdn.microsoft.com/en-us/library/windows/desktop/ms632664(v=vs.85).aspx) and MAKELPARAM.

How to design cleaner PostMessage chain in WinApi/MFC

I have a MFC GUI app that has multiple frames (sort of like Outlook'ish behavior with main window, and message/appointment windows being created in new frames, or Skype like multi frame syncronization), and I need to PostMessage malloc'ed data through the window hierarchy.
Say, I get the string, _wcsdup it, PostMessage(WM_NEWSTRING, ...), and, the control somewhere deep down the hierarchy processes it, or if there are no subscribers, the message get's cleaned.
What I am looking into now, is that all messages are posted to application thread, thread finds the active frame or best fit frame, passes the message to it, frame passes the message to it's view, the view passes message to subview and so on, if there is no view to process the message, it get's free'd.
The problem is that these chaining commands are pretty tiring to write, as I have to duplicate the message forwarding code in each CWnd class I have. At the same time, resource cleanup is pretty unpleasant, because if there is no window to catch the message, someone has to call the free. Therefore simply posting the message to the main message pump without extra handling, hoping that someone will always catch it, is not a valid approach. PostMessage returns S_OK, no one sees the message as processable, and it's left dangling.
Is there a better, correct approach for what I'm looking for?
I would never use PostMessage as you describe. My solution often involves a hand-shake:
// From CNotifierBlah
PostMesssage(hWnd, UWM_NEW_DATA, 0, 0);
//
LRESULT CDestinationWnd::OnNewData(WPARAM wParam, LPARAM lParam)
{
CNewData newData = GetNotifierBlah().GetNewData(); // Thread-safe getter!
}
Pretty much the same as Observer pattern.

Using the Windows SetTimer() function

I am getting confused with the SetTimer() function.
SetTimer() takes three parameters:
SetTimer(1,2000,Timerflow);
However I've seen another version of SetTimer that takes four parameters:
SetTimer(NULL,1,2000,Timerflow);
What is the difference between these two functions?
I know SetTimer() Three parameters. But when I try the four parameter SetTimer() function, I get the error:
error C2660: 'SetTimer' : function does not take 4 parameters
So what is the main difference and what causes this error?
The 4-parameter version is the plain Win32 API version, and the first parameter is a window handle.
The 3-parameter version is a member of MFC's CWnd class, and works with the window handle of the CWnd instance for which you call it.
If you need to call the 4-parameter Win32 API from within a method of a CWnd-derived object, do this:
::SetTimer(NULL, 1, 2000, Timerflow);
The only Windows API called SetTimer takes four parameters. Presumably the other one is part of MFC or some other framework, and the first parameter is implied by the object you call it on. For example:
CWnd * w = .... // get window somehow
w->SetTimer(1,2000,Timerflow);
If you use SetTimer to create a timer in GUI classes such as the MFC's CWnd, you can use the 3-parameter form:
UINT SetTimer(
UINT nIDEvent, // timer identifier
UINT uElapse, // time-out value
TIMERPROC lpTimerFunc // address of timer procedure
);
But if you use it in non-GUI classes, you have to use the 4-parameter form. The first parameter is to specify which GUI component will respond for the timer event. This version of the function is called from Win32 API.
eUINT SetTimer(
HWND hWnd, // handle of window for timer messages
UINT nIDEvent, // timer identifier
UINT uElapse, // time-out value
TIMERPROC lpTimerFunc // address of timer procedure
);
It is very simple, isn't it?
According to MSDN: https://msdn.microsoft.com/en-us/library/windows/desktop/ms644906(v=vs.85).aspx, the first and last parameters are optional. Therefore, you can have a SetTimer call with even 2 parameters (not recommended however). The error is most likely from an incorrect cast (needs a uint_ptr, you give an hwnd, for example)

How to correctly use SetWindowsHookEx & CallNextHookEx

I can correctly setup up a windows hook, but I get confused by the line in MSDN that says "Calling the CallNextHookEx function to chain to the next hook procedure is optional, but it is highly recommended; otherwise, other applications that have installed hooks will not receive hook notifications and may behave incorrectly as a result. You should call CallNextHookEx unless you absolutely need to prevent the notification from being seen by other applications.".
I want to be a good programming citizen and call the next hook. But, my hook procedure looks like this:
LRESULT CALLBACK CBTProc(int code, WPARAM wp, LPARAM lp)
{
if (code != HCBT_CREATEWND)
{
// What do I do here? It's not the event I requested so how do I pass it on?
return 0;
}
// It's the code we want (create window)
CallNextHookEx(...);
...
}
So, what happens in the hook procedure if the code isn't the one I'm interested in? How do I call the next hook?
Edit: The main problem is that a HHOOK is returned from the SetWindowsHookEx, and that needs to be passed to the CallNextHookEx function.
Update: It seems the hook parameter is ignored on the NT platforms:
http://msdn.microsoft.com/en-us/library/ms644974.aspx
http://www.klenotic.com/pl/null_hhook/
According to the docs, the proper thing to do is pass the arguments you received directly to CallNextHookEx, exactly as you received them. You should also call CallNextHookEx regardless of whether you decided to handle the hook message.
According to MSDN, the first parameter to CallNextHookEx is ignored on on NT/XP/2003, and for older Win95-based operating systems it should be the HHOOK you received when you registered your hook with SetWindowsHookEx. The docs don't specify a value for Windows 2000, but since it's part of the NT family, a reasonable guess is that it's ignored there as well.
Given all that, a good way to code the method for NT-family operating systems might be this:
LRESULT CALLBACK CBTProc( int code, WPARAM wp, LPARAM lp )
{
if( code == HCBT_CREATEWND )
ProcessCreateWnd( wp, lp );
return CallNextHookEx( 0, code, wp, lp );
}
void ProcessCreateWnd( WPARAM wp, LPARAM lp )
{
// my code here
}
This makes sure that you always call the hook at the end of your processing, and makes it hard to accidentally add a return that will bypass CallNextHookEx.

Resources