如何知道在 Win32 中选择的菜单项 API
How to know selected menu item in Win32 API
在 window API 中,我有一个弹出菜单,其中分别包含 3 个项目 "Line"、"Circle" 和 "Exit"。
我的程序是让用户select 绘制一个形状,然后获取点、参数(即线的起点和终点,...)。这是我到目前为止编写的代码的一部分。
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg,
WPARAM wParam, LPARAM lParam) {
HMENU hMenu;
POINT point;
HDC hdc;
hdc = GetDC(hwnd);
static int x1, y1,x2,y2,count = 0;
switch (msg) {
case WM_LBUTTONDOWN:
count++;
if (count == 1)
{
x1 = LOWORD(lParam);
y1 = HIWORD(lParam);
}
else
{
x2 = LOWORD(lParam);
y2 = HIWORD(lParam);
// I think the problem goes here, it never execute else part
//even if global_ID ==2, Am I missing something?
if (global_ID == 1)//Line
{DirectMethod(hdc, x1, y1, x2, y2, RGB(0, 0, 0));}
else if (global_ID == 2)//Circle
{Ellipse(hdc, x1, y1, x2, y2);}
count = 0;
}
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDM_FILE_LINE:
global_ID = 1;
break;
case IDM_FILE_CIRCLE:
global_ID = 2;//Global Variable
break;
case IDM_FILE_QUIT:
SendMessage(hwnd, WM_CLOSE, 0, 0);
break;
}
break;
case WM_RBUTTONUP:
point.x = LOWORD(lParam);
point.y = HIWORD(lParam);
hMenu = CreatePopupMenu();
ClientToScreen(hwnd, &point);
AppendMenuW(hMenu, MF_STRING, IDM_FILE_LINE, L"&line");
AppendMenuW(hMenu, MF_STRING, IDM_FILE_CIRCLE, L"&Circle");
AppendMenuW(hMenu, MF_SEPARATOR, 0, NULL);
AppendMenuW(hMenu, MF_STRING, IDM_FILE_QUIT, L"&Quit");
TrackPopupMenu(hMenu, TPM_RIGHTBUTTON, point.x, point.y, 0, hwnd, NULL);
DestroyMenu(hMenu);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProcW(hwnd, msg, wParam, lParam);
}
我想做的是,基于 selected 菜单项(线,圆,...)我执行特定的代码段,这也取决于从用户那里获得鼠标点击(WM_LBUTTONDOWN).
例如:
如果用户 selected "Line",我应该取两个点来画那条线。
您的代码中存在逻辑漏洞:
您正在计算鼠标点击次数,即使您不应该这样做。当您的 WM_COMMAND
处理程序设置 global_ID
时,您不会同时将 count
重置为 0,因此后续点击可能会跳过 x1
/y1
的分配因为 count
可能已经是 > 0
.
当 global_ID
不是 1 或 2 时,您的 WM_LBUTTONDOWN
处理程序根本不应该做任何事情。
您在调用 DirectMethod()
/Ellipse()
后并未重置 global_ID
,因此 WM_LBUTTONDOWN
只会不断计算点击次数并在每隔一次点击。
您的 WM_LBUTTONDOWN
缺少必需的 break
语句,因此每条 WM_LBUTTONDOWN
消息都将落入 WM_COMMAND
代码。
试试这个:
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
static int x1, y1, x2, y2, count = 0, global_ID = 0;
switch (msg)
{
case WM_LBUTTONDOWN:
{
switch (global_ID)
{
case 1: //Line
case 2: //Circle
{
++count;
if (count == 1)
{
x1 = GET_X_LPARAM(lParam);
y1 = GET_Y_LPARAM(lParam);
}
else
{
x2 = GET_X_LPARAM(lParam);
y2 = GET_Y_LPARAM(lParam);
HDC hdc = GetDC(hwnd);
if (global_ID == 1) {
DirectMethod(hdc, x1, y1, x2, y2, RGB(0, 0, 0));
}
else {
Ellipse(hdc, x1, y1, x2, y2);
}
ReleaseDC(hwnd, hdc);
global_ID = 0;
}
break;
}
}
break;
}
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case IDM_FILE_LINE:
global_ID = 1;
count = 0;
break;
case IDM_FILE_CIRCLE:
global_ID = 2;
count = 0;
break;
case IDM_FILE_QUIT:
SendMessage(hwnd, WM_CLOSE, 0, 0);
break;
}
break;
}
case WM_RBUTTONUP:
{
POINT point;
point.x = GET_X_LPARAM(lParam);
point.y = GET_Y_LPARAM(lParam);
ClientToScreen(hwnd, &point);
HMENU hMenu = CreatePopupMenu();
AppendMenuW(hMenu, MF_STRING, IDM_FILE_LINE, L"&line");
AppendMenuW(hMenu, MF_STRING, IDM_FILE_CIRCLE, L"&Circle");
AppendMenuW(hMenu, MF_SEPARATOR, 0, NULL);
AppendMenuW(hMenu, MF_STRING, IDM_FILE_QUIT, L"&Quit");
TrackPopupMenu(hMenu, TPM_RIGHTBUTTON, point.x, point.y, 0, hwnd, NULL);
DestroyMenu(hMenu);
break;
}
case WM_DESTROY:
{
PostQuitMessage(0);
break;
}
}
return DefWindowProcW(hwnd, msg, wParam, lParam);
}
在 window API 中,我有一个弹出菜单,其中分别包含 3 个项目 "Line"、"Circle" 和 "Exit"。
我的程序是让用户select 绘制一个形状,然后获取点、参数(即线的起点和终点,...)。这是我到目前为止编写的代码的一部分。
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg,
WPARAM wParam, LPARAM lParam) {
HMENU hMenu;
POINT point;
HDC hdc;
hdc = GetDC(hwnd);
static int x1, y1,x2,y2,count = 0;
switch (msg) {
case WM_LBUTTONDOWN:
count++;
if (count == 1)
{
x1 = LOWORD(lParam);
y1 = HIWORD(lParam);
}
else
{
x2 = LOWORD(lParam);
y2 = HIWORD(lParam);
// I think the problem goes here, it never execute else part
//even if global_ID ==2, Am I missing something?
if (global_ID == 1)//Line
{DirectMethod(hdc, x1, y1, x2, y2, RGB(0, 0, 0));}
else if (global_ID == 2)//Circle
{Ellipse(hdc, x1, y1, x2, y2);}
count = 0;
}
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDM_FILE_LINE:
global_ID = 1;
break;
case IDM_FILE_CIRCLE:
global_ID = 2;//Global Variable
break;
case IDM_FILE_QUIT:
SendMessage(hwnd, WM_CLOSE, 0, 0);
break;
}
break;
case WM_RBUTTONUP:
point.x = LOWORD(lParam);
point.y = HIWORD(lParam);
hMenu = CreatePopupMenu();
ClientToScreen(hwnd, &point);
AppendMenuW(hMenu, MF_STRING, IDM_FILE_LINE, L"&line");
AppendMenuW(hMenu, MF_STRING, IDM_FILE_CIRCLE, L"&Circle");
AppendMenuW(hMenu, MF_SEPARATOR, 0, NULL);
AppendMenuW(hMenu, MF_STRING, IDM_FILE_QUIT, L"&Quit");
TrackPopupMenu(hMenu, TPM_RIGHTBUTTON, point.x, point.y, 0, hwnd, NULL);
DestroyMenu(hMenu);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProcW(hwnd, msg, wParam, lParam);
}
我想做的是,基于 selected 菜单项(线,圆,...)我执行特定的代码段,这也取决于从用户那里获得鼠标点击(WM_LBUTTONDOWN).
例如: 如果用户 selected "Line",我应该取两个点来画那条线。
您的代码中存在逻辑漏洞:
您正在计算鼠标点击次数,即使您不应该这样做。当您的
WM_COMMAND
处理程序设置global_ID
时,您不会同时将count
重置为 0,因此后续点击可能会跳过x1
/y1
的分配因为count
可能已经是> 0
.当
global_ID
不是 1 或 2 时,您的WM_LBUTTONDOWN
处理程序根本不应该做任何事情。您在调用
DirectMethod()
/Ellipse()
后并未重置global_ID
,因此WM_LBUTTONDOWN
只会不断计算点击次数并在每隔一次点击。您的
WM_LBUTTONDOWN
缺少必需的break
语句,因此每条WM_LBUTTONDOWN
消息都将落入WM_COMMAND
代码。
试试这个:
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
static int x1, y1, x2, y2, count = 0, global_ID = 0;
switch (msg)
{
case WM_LBUTTONDOWN:
{
switch (global_ID)
{
case 1: //Line
case 2: //Circle
{
++count;
if (count == 1)
{
x1 = GET_X_LPARAM(lParam);
y1 = GET_Y_LPARAM(lParam);
}
else
{
x2 = GET_X_LPARAM(lParam);
y2 = GET_Y_LPARAM(lParam);
HDC hdc = GetDC(hwnd);
if (global_ID == 1) {
DirectMethod(hdc, x1, y1, x2, y2, RGB(0, 0, 0));
}
else {
Ellipse(hdc, x1, y1, x2, y2);
}
ReleaseDC(hwnd, hdc);
global_ID = 0;
}
break;
}
}
break;
}
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case IDM_FILE_LINE:
global_ID = 1;
count = 0;
break;
case IDM_FILE_CIRCLE:
global_ID = 2;
count = 0;
break;
case IDM_FILE_QUIT:
SendMessage(hwnd, WM_CLOSE, 0, 0);
break;
}
break;
}
case WM_RBUTTONUP:
{
POINT point;
point.x = GET_X_LPARAM(lParam);
point.y = GET_Y_LPARAM(lParam);
ClientToScreen(hwnd, &point);
HMENU hMenu = CreatePopupMenu();
AppendMenuW(hMenu, MF_STRING, IDM_FILE_LINE, L"&line");
AppendMenuW(hMenu, MF_STRING, IDM_FILE_CIRCLE, L"&Circle");
AppendMenuW(hMenu, MF_SEPARATOR, 0, NULL);
AppendMenuW(hMenu, MF_STRING, IDM_FILE_QUIT, L"&Quit");
TrackPopupMenu(hMenu, TPM_RIGHTBUTTON, point.x, point.y, 0, hwnd, NULL);
DestroyMenu(hMenu);
break;
}
case WM_DESTROY:
{
PostQuitMessage(0);
break;
}
}
return DefWindowProcW(hwnd, msg, wParam, lParam);
}