Files

138 lines
5.2 KiB
C

// SPDX-License-Identifier: LGPL-2.1-or-later
#define COBJMACROS
#include <windows.h>
#include <initguid.h>
#include <oleacc.h>
static HMENU bar, file, edit, nested, context;
static int step;
static HWND marshaledControl;
static HWND button;
static LRESULT CALLBACK provider_proc(HWND window, UINT message, WPARAM wp, LPARAM lp) {
if (message == WM_GETOBJECT && (LONG)lp == OBJID_CLIENT) {
IAccessible *accessible = NULL;
if (SUCCEEDED(CreateStdAccessibleObject(window, OBJID_CLIENT, &IID_IAccessible,
(void **)&accessible))) {
// Returning a marshaled object forces the separate helper to use COM,
// rather than Wine's directly constructed native-control proxy.
LRESULT result = LresultFromObject(&IID_IAccessible, wp, (IUnknown *)accessible);
IAccessible_Release(accessible);
return result;
}
}
return DefWindowProcW(window, message, wp, lp);
}
static LRESULT CALLBACK window_proc(HWND window, UINT message, WPARAM wp, LPARAM lp) {
if (message == WM_TIMER) {
switch (++step) {
case 1:
SetFocus(button);
// Enter File through the application's actual native menu loop.
PostMessageW(window, WM_SYSCOMMAND, SC_KEYMENU, 'f');
break;
case 2: case 3:
PostMessageW(window, WM_KEYDOWN, VK_DOWN, 1);
break;
case 4:
PostMessageW(window, WM_KEYDOWN, VK_RIGHT, 1);
break;
case 5:
PostMessageW(window, WM_KEYDOWN, VK_ESCAPE, 1);
break;
case 6:
PostMessageW(window, WM_KEYDOWN, VK_ESCAPE, 1);
break;
case 7:
// Context menus use a separate HMENU, unrelated to the menu bar.
TrackPopupMenu(context, TPM_LEFTALIGN, 200, 200, 0, window, NULL);
break;
case 8:
PostMessageW(window, WM_KEYDOWN, VK_DOWN, 1);
break;
case 9:
PostMessageW(window, WM_KEYDOWN, VK_ESCAPE, 1);
break;
case 10:
AppendMenuW(file, MF_STRING | MF_CHECKED | MF_GRAYED, 104, L"Pinned && &offline\tCtrl+P");
/* fall through */
case 11:
// Also exercise checked/disabled items and duplicate notifications.
SendMessageW(window, WM_MENUSELECT, MAKEWPARAM(104, MF_CHECKED | MF_GRAYED), (LPARAM)file);
break;
case 12:
SendMessageW(window, WM_MENUSELECT, MAKEWPARAM(0, 0xffff), 0);
break;
case 13:
SendMessageW(window, WM_MENUSELECT, MAKEWPARAM(104, MF_CHECKED | MF_GRAYED), (LPARAM)file);
break;
case 14:
PostMessageW(window, WM_SYSCOMMAND, SC_KEYMENU, 'f');
break;
case 15:
// Move from Open to the submenu using ordinary menu navigation.
PostMessageW(window, WM_KEYDOWN, VK_DOWN, 1);
PostMessageW(window, WM_KEYDOWN, VK_DOWN, 1);
PostMessageW(window, WM_KEYDOWN, VK_DOWN, 1);
break;
case 16:
PostMessageW(window, WM_KEYDOWN, VK_RIGHT, 1);
break;
case 17: case 18: case 19:
PostMessageW(window, WM_KEYDOWN, VK_ESCAPE, 1);
break;
default:
DestroyWindow(window);
break;
}
return 0;
}
if (message == WM_DESTROY) { PostQuitMessage(0); return 0; }
return DefWindowProcW(window, message, wp, lp);
}
int WINAPI WinMain(HINSTANCE instance, HINSTANCE previous, LPSTR args, int show) {
(void)previous; (void)args; (void)show;
if (FAILED(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED))) return 1;
WNDCLASSW cls = {0};
cls.hInstance = instance;
cls.lpszClassName = L"WineAccessMenuFixture";
cls.lpfnWndProc = window_proc;
RegisterClassW(&cls);
bar = CreateMenu(); file = CreatePopupMenu(); edit = CreatePopupMenu();
nested = CreatePopupMenu(); context = CreatePopupMenu();
AppendMenuW(file, MF_STRING, 101, L"&Open\tCtrl+O");
AppendMenuW(file, MF_STRING | MF_CHECKED, 102, L"&Word wrap");
AppendMenuW(file, MF_STRING | MF_CHECKED | MF_GRAYED, 103, L"Save && &close\tCtrl+S");
AppendMenuW(nested, MF_STRING, 401, L"&Nested action");
AppendMenuW(file, MF_POPUP, (UINT_PTR)nested, L"&Favorites");
AppendMenuW(edit, MF_STRING, 302, L"&Cut\tCtrl+X");
AppendMenuW(context, MF_STRING, 201, L"&Context action");
AppendMenuW(bar, MF_POPUP, (UINT_PTR)file, L"&File");
AppendMenuW(bar, MF_POPUP, (UINT_PTR)edit, L"&Edit");
HWND window = CreateWindowW(cls.lpszClassName, L"Wine menu fixture", WS_OVERLAPPEDWINDOW,
120, 120, 400, 240, NULL, bar, instance, NULL);
ShowWindow(window, SW_SHOW);
button = CreateWindowW(L"Button", L"Return to control", WS_CHILD | WS_VISIBLE | WS_TABSTOP,
10, 10, 200, 30, window, NULL, instance, NULL);
cls.lpszClassName = L"WineAccessMarshaledFixture";
cls.lpfnWndProc = provider_proc;
RegisterClassW(&cls);
marshaledControl = CreateWindowW(cls.lpszClassName, L"Application-owned accessibility",
WS_CHILD | WS_VISIBLE | WS_TABSTOP,
10, 60, 250, 30, window, NULL, instance, NULL);
SetForegroundWindow(window);
SetFocus(button);
SetFocus(marshaledControl);
NotifyWinEvent(EVENT_OBJECT_FOCUS, marshaledControl, OBJID_CLIENT, CHILDID_SELF);
SetTimer(window, 1, 400, NULL);
MSG message;
while (GetMessageW(&message, NULL, 0, 0) > 0) {
TranslateMessage(&message); DispatchMessageW(&message);
}
DestroyMenu(context);
CoUninitialize();
return 0;
}