NO

Author Topic: WM_DROPFILES  (Read 4390 times)

CLR

  • Guest
WM_DROPFILES
« on: November 17, 2013, 03:11:08 am »
I would post this as 'WM_DROPFILES doesn't work', but I've found the cause. I'm posting it anyway ...
When I run the following program from the Pelles C IDE, WM_DROPFILES isn't fired because the process is run with Admin privileges, while Explorer is run with normal user account, so nothing happens when I drop a file from Explorer.  :P

Code: [Select]
#define WIN32_LEAN_AND_MEAN
#define UNICODE
#define _UNICODE

#include <windows.h>
#include <tchar.h>
#include <shellapi.h>

#pragma lib "shell32.lib"

LRESULT CALLBACK MainWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch(msg)
    {
case WM_CREATE:
DragAcceptFiles(hwnd, TRUE);
break;

case WM_DROPFILES:
MessageBox(hwnd, L"WM_DROPFILES", L"WM_DROPFILES", 0);
break;

        case WM_DESTROY:
DragAcceptFiles(hwnd, FALSE);
            PostQuitMessage(0);
        break;

        default:
            return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    HWND hwnd;
    MSG msg;

    WNDCLASSEX wc;

    wc.cbSize        = sizeof(WNDCLASSEX);
    wc.style         = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc   = MainWndProc;
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = 0;
    wc.hInstance     = hInstance;
    wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
    wc.lpszMenuName  = NULL;
    wc.lpszClassName = _T("myWindowClass");
    wc.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);

RegisterClassEx(&wc);

    hwnd = CreateWindowEx(0,
_T("myWindowClass"),
_T("My Program"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
380, 320,
NULL, NULL, hInstance, NULL);

    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

    while (GetMessage(&msg, NULL, 0, 0) > 0)
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return (int) msg.wParam;
}

Offline DMac

  • Member
  • *
  • Posts: 255
Re: WM_DROPFILES
« Reply #1 on: November 20, 2013, 01:49:18 am »
No one cares how much you know,
until they know how much you care.

CLR

  • Guest
Re: WM_DROPFILES
« Reply #2 on: November 20, 2013, 02:53:36 am »

laurro

  • Guest
Re: WM_DROPFILES
« Reply #3 on: November 21, 2013, 09:16:41 am »
  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.

Code: [Select]
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

Code: [Select]
#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

CLR

  • Guest
Re: WM_DROPFILES
« Reply #4 on: November 23, 2013, 11:46:50 pm »
Hi laurro.
Thanks for the code. I'll try it.