I'm trying to fix SHBrowseForFolder dialog, as it doesn't react on folder renaming (BFFM_SELCHANGED isn't being sent and there is no way to determine is the path now correct or not). I googled a solution, which said like I have to subclass dlg's wndproc and catch TVN_ENDLABELEDIT to send BFFM_SELCHANGED myself.
Here is how I set new wndproc when I get BFFM_INITIALIZED:
for (HWND hChild = GetWindow(hWnd, GW_CHILD); hChild != 0; hChild = GetWindow(hChild, GW_HWNDNEXT)) {
szClassName[256];
GetClassName(hChild, szClassName, sizeof(szClassName));
if (!stricmp(szClassName, "SHBROWSEFORFOLDER SHELLNAMESPACE CONTROL")) {
oldWndProc = reinterpret_cast<WNDPROC>(SetWindowLongPtr(hChild, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(_SubclassWndProc)));
break;
}
}
Here is _SubclassWndProc:
static LRESULT _SubclassWndProc(HWND hWnd, UINT uMsg, WPARAM lParam, LPARAM lpData) {
switch (uMsg) {
case WM_NOTIFY:
switch (((LPNMHDR)lParam)->code) {
case TVN_ENDLABELEDIT:
break;
}
break;
}
return CallWindowProc(oldWndProc, hWnd, uMsg, lParam, lpData);
}
It works only if I comment WM_NOTIFY block. Even an access to lParam breaks dialog (it contains corrupted treee with empty labels). If I call oldWndProc before switch, then it works, but in WM_NOTIFY case lParam obviously doesn't contain a pointer to NMHDR, it contains a small integer value like 1,2,100 etc.
Edit: The question can be shortened to "Why does WM_NOTIFY come without a pointer to NMHDR?"
The error was due to my negligence: I copied wndproc signature from some example, which has agrument names confused. The lParam usually comes last and has a type LPARAM. So I was trying to cast arg usually called wParam, which contains a control id not LPNMHDR.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With