📄 fakemenu.c
字号:
*/
/*
* If too high, then slide down.
*/
if (ppt->y < minf.rcMonitor.top) {
ppt->y = minf.rcMonitor.top;
}
/*
* If too far left, then slide right.
*/
if (ppt->x < minf.rcMonitor.left) {
ppt->x = minf.rcMonitor.left;
}
/*
* If too low, then slide up.
*/
if (ppt->y > minf.rcMonitor.bottom - cy) {
ppt->y = minf.rcMonitor.bottom - cy;
}
/*
* If too far right, then flip left.
*/
if (ppt->x > minf.rcMonitor.right - cx) {
ppt->x = ppt->x - cx;
}
}
/*****************************************************************************
*
* ColorPick_Popup
*
* Display a fake menu to allow the user to select the color.
*
* Return the color index the user selected, or -1 if no color
* was selected.
*
*****************************************************************************/
int
ColorPick_Popup(HWND hwndOwner, int x, int y)
{
COLORPICKSTATE cps;
HWND hwndPopup, hwndActive;
RECT rc;
DWORD dwStyle, dwExStyle;
MSG msg;
POINT pt;
int cx, cy;
/*
* Early check: We must be on same thread as the owner
* so we can see its mouse and keyboard messages when we
* set capture to it.
*/
if (GetCurrentThreadId() != GetWindowThreadProcessId(hwndOwner, NULL)) {
/*
* Error: Menu must be on same thread as parent window.
*/
return -1;
}
cps.fDone = FALSE; /* Not done yet */
cps.iSel = -1; /* No initial selection */
cps.iResult = -1; /* No result */
cps.hwndOwner = hwndOwner; /* Owner window */
/*
* The style and extended style we want to use.
*/
dwStyle = WS_POPUP | WS_BORDER;
dwExStyle = WS_EX_TOOLWINDOW | /* So it doesn't show up in taskbar */
WS_EX_DLGMODALFRAME | /* Get the edges right */
WS_EX_WINDOWEDGE |
WS_EX_TOPMOST; /* So it isn't obscured */
/*
* We want a client area of size (CXFAKEMENU, CCLRPREDEF * CYCOLOR),
* so use AdjustWindowRectEx to figure out what window rect will
* give us a client rect of that size.
*/
rc.left = 0;
rc.top = 0;
rc.right = CXFAKEMENU;
rc.bottom = CCLRPREDEF * CYCOLOR;
AdjustWindowRectEx(&rc, dwStyle, FALSE, dwExStyle);
/*
* Now find a proper home for the window that won't go off
* the screen or straddle two monitors.
*/
cx = rc.right - rc.left;
cy = rc.bottom - rc.top;
ColorPick_ChooseLocation(hwndOwner, x, y, cx, cy, &pt);
hwndPopup = CreateWindowEx(
dwExStyle, /* Extended style */
"ColorPick", /* Class Name */
"", /* Title */
dwStyle, /* Style */
pt.x, pt.y, /* Position */
cx, cy, /* Size */
hwndOwner, /* Parent */
NULL, /* No menu */
g_hinst, /* Instance */
&cps); /* Starting parameters */
/*
* Show the window but don't activate it!
*/
ShowWindow(hwndPopup, SW_SHOWNOACTIVATE);
/*
* We want to receive all mouse messages, but since
* only the active window can capture the mouse,
* we have to set the capture to our owner window,
* and then steal the mouse messages out from under him.
*/
SetCapture(hwndOwner);
/*
* Go into a message loop that filters all the messages
* it receives and routes the interesting ones to the
* color picker window.
*/
while (GetMessage(&msg, NULL, 0, 0)) {
/*
* Something may have happened that caused us to stop.
* If so, then stop.
*/
if (cps.fDone) break;
/*
* If our owner stopped being the active window
* (e.g., the user Alt+Tab'd to another window
* in the meantime), then stop.
*/
hwndActive = GetActiveWindow();
if (hwndActive != hwndOwner &&
!IsChild(hwndActive, hwndOwner)) break;
if (GetCapture() != hwndOwner) break;
/*
* At this point, we get to snoop at all input messages
* before they get dispatched. This allows us to
* route all input to our popup window even if really
* belongs to somebody else.
*
* All mouse messages are remunged and directed at our
* popup menu. If the mouse message arrives as client
* coordinates, then we have to convert it from the
* client coordinates of the original target to the
* client coordinates of the new target.
*/
switch (msg.message) {
/*
* These mouse messages arrive in client coordinates,
* so in addition to stealing the message, we also
* need to convert the coordinates.
*/
case WM_MOUSEMOVE:
case WM_LBUTTONDOWN:
case WM_LBUTTONUP:
case WM_LBUTTONDBLCLK:
case WM_RBUTTONDOWN:
case WM_RBUTTONUP:
case WM_RBUTTONDBLCLK:
case WM_MBUTTONDOWN:
case WM_MBUTTONUP:
case WM_MBUTTONDBLCLK:
pt.x = (short)LOWORD(msg.lParam);
pt.y = (short)HIWORD(msg.lParam);
MapWindowPoints(msg.hwnd, hwndPopup, &pt, 1);
msg.lParam = MAKELPARAM(pt.x, pt.y);
msg.hwnd = hwndPopup;
break;
/*
* These mouse messages arrive in screen coordinates,
* so we just need to steal the message.
*/
case WM_NCMOUSEMOVE:
case WM_NCLBUTTONDOWN:
case WM_NCLBUTTONUP:
case WM_NCLBUTTONDBLCLK:
case WM_NCRBUTTONDOWN:
case WM_NCRBUTTONUP:
case WM_NCRBUTTONDBLCLK:
case WM_NCMBUTTONDOWN:
case WM_NCMBUTTONUP:
case WM_NCMBUTTONDBLCLK:
msg.hwnd = hwndPopup;
break;
/*
* Steal all keyboard messages, too.
*/
case WM_KEYDOWN:
case WM_KEYUP:
case WM_CHAR:
case WM_DEADCHAR:
case WM_SYSKEYDOWN:
case WM_SYSKEYUP:
case WM_SYSCHAR:
case WM_SYSDEADCHAR:
msg.hwnd = hwndPopup;
break;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
/*
* Something may have happened that caused us to stop.
* If so, then stop.
*/
if (cps.fDone) break;
/*
* If our owner stopped being the active window
* (e.g., the user Alt+Tab'd to another window
* in the meantime), then stop.
*/
hwndActive = GetActiveWindow();
if (hwndActive != hwndOwner &&
!IsChild(hwndActive, hwndOwner)) break;
if (GetCapture() != hwndOwner) break;
}
/*
* Clean up the capture we created.
*/
ReleaseCapture();
DestroyWindow(hwndPopup);
/*
* If we got a WM_QUIT message, then re-post it so the caller's
* message loop will see it.
*/
if (msg.message == WM_QUIT) {
PostQuitMessage((int)msg.wParam);
}
return cps.iResult;
}
/*****************************************************************************
*
* FakeMenuDemo_OnEraseBkgnd
*
* Erase the background in the selected color.
*
*****************************************************************************/
void
FakeMenuDemo_OnEraseBkgnd(HWND hwnd, HDC hdc)
{
RECT rc;
GetClientRect(hwnd, &rc);
FillRect(hdc, &rc, g_hbrColor);
}
/*****************************************************************************
*
* FakeMenuDemo_OnContextMenu
*
* Display the color-picker pseudo-menu so the user can change
* the color.
*
*****************************************************************************/
void
FakeMenuDemo_OnContextMenu(HWND hwnd, int x, int y)
{
int iColor;
/*
* If the coordinates are (-1, -1), then the user typed Shift+F10,
* so we should pretend the user clicked at client (0, 0).
*/
if (x == -1 && y == -1) {
POINT pt;
pt.x = 0;
pt.y = 0;
ClientToScreen(hwnd, &pt);
x = pt.x;
y = pt.y;
}
iColor = ColorPick_Popup(hwnd, x, y);
/*
* If the user picked a color, then change to that color.
*/
if (iColor >= 0) {
DeleteObject(g_hbrColor);
g_hbrColor = CreateSolidBrush(c_rgclrPredef[iColor]);
InvalidateRect(hwnd, NULL, TRUE);
}
}
/*****************************************************************************
*
* FakeMenuDemo_WndProc
*
* Window procedure for the fake menu demo.
*
*****************************************************************************/
LRESULT CALLBACK
FakeMenuDemo_WndProc(HWND hwnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)
{
switch (uiMsg) {
case WM_ERASEBKGND:
FakeMenuDemo_OnEraseBkgnd(hwnd, (HDC)wParam);
return TRUE;
case WM_CONTEXTMENU:
FakeMenuDemo_OnContextMenu(hwnd, (short)LOWORD(lParam),
(short)HIWORD(lParam));
return 0;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(hwnd, uiMsg, wParam, lParam);
}
/*****************************************************************************
*
* InitClasses
*
* Register our window classes.
*
* "FakeMenuDemo" is the class for the main window.
*
* "ColorPick" is the class for our color-picker pseudo-menu.
*
*****************************************************************************/
void
InitClasses(void)
{
WNDCLASS wc;
wc.style = 0;
wc.lpfnWndProc = ColorPick_WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = g_hinst;
wc.hIcon = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = "ColorPick";
RegisterClass(&wc);
wc.style = 0;
wc.lpfnWndProc = FakeMenuDemo_WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = g_hinst;
wc.hIcon = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = NULL; /* Background color is dynamic */
wc.lpszMenuName = NULL;
wc.lpszClassName = "FakeMenuDemo";
RegisterClass(&wc);
}
/*****************************************************************************
*
* WinMain
*
* Program entry point.
*
* Demonstrate pseudo-menus.
*
*****************************************************************************/
int WINAPI
WinMain(HINSTANCE hinst, HINSTANCE hinstPrev, LPSTR pszCmdLine, int nCmdShow)
{
MSG msg;
HWND hwnd;
g_hinst = hinst;
InitClasses();
/*
* Start out white.
*/
g_hbrColor = CreateSolidBrush(RGB(0xFF, 0xFF, 0xFF));
hwnd = CreateWindow(
"FakeMenuDemo", /* Class Name */
"Fake Menu Demo - Right-click in window to change color", /* Title */
WS_OVERLAPPEDWINDOW, /* Style */
CW_USEDEFAULT, CW_USEDEFAULT, /* Position */
CW_USEDEFAULT, CW_USEDEFAULT, /* Size */
NULL, /* Parent */
NULL, /* No menu */
hinst, /* Instance */
0); /* No special parameters */
ShowWindow(hwnd, nCmdShow);
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -