Reputation: 379
In window API, I have a popup menu which contains 3 items "Line","Circle" and "Exit" respectively.
My program is to let the user select a shape to draw then takes the points, parameters (i.e. start and end points of the line,...). This is part of the code i've written so far.
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);
}
What I wanna do is, based on selected menu item (Line, Circle,...) I execute specific piece of code which depends also on getting mouse clicks from user (WM_LBUTTONDOWN).
For example: If the user selected "Line", I should take two points to draw that line.
Upvotes: 1
Views: 2079
Reputation: 597941
There are logic holes in your code:
you are counting mouse clicks even when you shouldn't be. When your WM_COMMAND
handler sets global_ID
, you are not also resetting count
to 0, so a subsequent click may end up skipping the assignment of x1
/y1
since count
may already be > 0
.
your WM_LBUTTONDOWN
handler should not be doing anything at all when global_ID
is not 1 or 2.
you are not resetting global_ID
after calling DirectMethod()
/Ellipse()
, so WM_LBUTTONDOWN
will just keep counting clicks endlessly and performing its drawings on every other click.
your WM_LBUTTONDOWN
is missing a required break
statement, so every WM_LBUTTONDOWN
message will fall through to the WM_COMMAND
code.
Try this instead:
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);
}
Upvotes: 2