Hi CLR, hi DMac.
Usually I use WM_DROPFILES as a cheap alternative to the GetOpenFileName(), and I was not aware of
the problem until the CLR's post (I keep UAC turned off, I almost forgot how ugly it is).
So thank you CLR.
DMac thanks for your solution, but user32.dll in Vista does not have ChangeWindowMessageFilterEx(),
I checked. So I looked for a solution on internet and I found ChangeWindowMessageFilter(), has several
advantages: is already in the SDK, works in Vista and 7 (I tested) I do not know about 8, you can start
or stop the filter if you have UAC turned on, if it is off ChangeWindowMessageFilter() is simply ignored.
here is my function I kept the same name and I still use function pointers to prevent the crashing of the
programm if is running on OSs bellow Vista and you use ChangeWindowMessageFilter() from user32.lib
(the IAT table will contained a entry with this name and the exe will crash. But this is just in theory, I can't
test this.
void EnableDragDrop(BOOL enable)
{
OSVERSIONINFO osvi;
ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&osvi);
if (osvi.dwMajorVersion < 6)
return;
typedef BOOL(__stdcall *pf) (UINT, DWORD);
HMODULE user32 = LoadLibrary(L"user32.dll");
if (user32)
{
pf ChangeWindowMessageFilter = (pf)GetProcAddress(user32, "ChangeWindowMessageFilter");
if (ChangeWindowMessageFilter)
{
DWORD dwFlag = enable ? MSGFLT_ADD : MSGFLT_REMOVE;
ChangeWindowMessageFilter(WM_DROPFILES, dwFlag);
ChangeWindowMessageFilter(WM_COPYDATA, dwFlag);
ChangeWindowMessageFilter(0x0049, dwFlag); //WM_COPYGLOBALDATA
}
FreeLibrary(user32);
}
}
and a simple test
#define UNICODE
#include <windows.h>
#pragma comment (lib,"shell32.lib")
void EnableDragDrop(BOOL enable)
{
OSVERSIONINFO osvi;
ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&osvi);
if (osvi.dwMajorVersion < 6)
return;
typedef BOOL(__stdcall *pf) (UINT, DWORD);
HMODULE user32 = LoadLibrary(L"user32.dll");
if (user32)
{
pf ChangeWindowMessageFilter = (pf)GetProcAddress(user32, "ChangeWindowMessageFilter");
if (ChangeWindowMessageFilter)
{
DWORD dwFlag = enable ? MSGFLT_ADD : MSGFLT_REMOVE;
ChangeWindowMessageFilter(WM_DROPFILES, dwFlag);
ChangeWindowMessageFilter(WM_COPYDATA, dwFlag);
ChangeWindowMessageFilter(0x0049, dwFlag); //WM_COPYGLOBALDATA
}
FreeLibrary(user32);
}
}
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
MSG msg = { 0 };
WNDCLASS wc = { 0 };
HWND hwnd;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpszClassName = L"WindowClassName";
wc.hInstance = hInstance;
wc.hbrBackground = GetSysColorBrush(COLOR_WINDOW);
wc.lpszMenuName = NULL;
wc.lpfnWndProc = WndProc;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
RegisterClass(&wc);
hwnd = CreateWindow(wc.lpszClassName, L"OFF", WS_OVERLAPPEDWINDOW, 10, 10, 500, 500, NULL, NULL, hInstance, NULL);
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_CREATE:
{
DragAcceptFiles(hwnd, TRUE);
return 0;
}
case WM_LBUTTONDOWN:
{
SetWindowText(hwnd, L"ON");
EnableDragDrop(TRUE);
}
break;
case WM_RBUTTONDOWN:
{
SetWindowText(hwnd, L"OFF");
EnableDragDrop(FALSE);
}
break;
case WM_DROPFILES:
{
wchar_t name[MAX_PATH] = { 0 };
DragQueryFile((HANDLE)wParam, 0, name, MAX_PATH);
DragFinish((HDROP)wParam);
RECT rc;
GetClientRect(hwnd, &rc);
HDC hdc = GetDC(hwnd);
PatBlt(hdc, 0, 0, rc.right, rc.bottom, WHITENESS);
DrawText(hdc, name, -1, &rc, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
ReleaseDC(hwnd, hdc);
}
break;
case WM_DESTROY:
{
DragAcceptFiles(hwnd, FALSE);
PostQuitMessage(0);
return 0;
}
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
Laur