LRESULT CALLBACK __tagCClassicButton::HandleMessage(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_LBUTTONDOWN: { this->pressed = true; this->RepaintComponent(); SetCapture(hWnd); } break; case WM_LBUTTONUP: { int mx = (int)((short)LOWORD(lParam)), my = (int)((short)HIWORD(lParam)); RECT wnd_bounds; GetWindowRect(hWnd, &wnd_bounds); this->pressed = false; this->RepaintComponent(); if (IsPointInArea(mx, my, 0, 0, MAKEWIDTH(wnd_bounds), MAKEHEIGHT(wnd_bounds))) { if (this->event_listener) // User clicked on button this->event_listener(this, message, wParam, lParam); } ReleaseCapture(); } break; case WM_KEYDOWN: { short key_code = (short)wParam; if (key_code == VK_RETURN) { if (this->event_listener) this->event_listener(this, message, wParam, lParam); } } break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; }
void Unit::Order_NukeLaunch(ProgressUnitResults *results) { if (order_state < 5 && !related) { Kill(results); return; } switch (order_state) { case 0: PlaySound(Sound::NukeLaunch, this, 1, 0); // Wtf ChangeMovementTarget(Point(sprite->position.x, units_dat_dimensionbox[NuclearMissile].top)); unk_move_waypoint = Point(sprite->position.x, units_dat_dimensionbox[NuclearMissile].top); order_timer = 90; order_state = 1; break; case 1: if (order_timer > 45 && IsStandingStill() == 0) return; PlaySound(Sound::Advisor_NukeLaunch + *bw::player_race, nullptr, 1, 0); PrintInfoMessage((*bw::stat_txt_tbl)->GetTblString(String::NuclearLaunchDetected)); order_state = 2; break; case 2: if (order_timer && IsStandingStill() == 0) return; HideUnit(this); related->related = this; StopMoving(this); order_state = 3; break; case 3: if (flingy_flags & 0x2) return; SetIscriptAnimation(Iscript::Animation::WarpIn, true, "Order_NukeLaunch state 3", results); order_state = 4; break; case 4: { if (~order_signal & 0x2) return; order_signal &= ~0x2; Point new_pos = order_target_pos; new_pos.x = std::max(units_dat_dimensionbox[NuclearMissile].left, new_pos.x); new_pos.y = std::max((int)units_dat_dimensionbox[NuclearMissile].top, new_pos.y - 0x140); MoveUnit(this, new_pos.x, new_pos.y); SetDirection((Flingy *)this, 0x80); ChangeMovementTarget(order_target_pos); unk_move_waypoint = order_target_pos; ShowUnit(this); order_state = 5; } break; case 5: if (!IsPointInArea(this, 10, move_target.x, move_target.y)) return; target = this; SetIscriptAnimation(Iscript::Animation::Special1, true, "Order_NukeLaunch state 5", results); order_state = 6; break; case 6: if (~order_signal & 0x1) return; order_signal &= ~0x1; order_flags |= 0x4; Kill(results); break; } }
LRESULT CALLBACK Internal_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { HPOPUP popup = (HPOPUP)GetWindowLong(hWnd, GWLP_USERDATA); switch (message) { case WM_PAINT: { HDC hdc; PAINTSTRUCT paintstruct; hdc = BeginPaint(hWnd, &paintstruct); DRAWCONTEXT context; context.paintstruct = paintstruct; context.fill_color = CLASSIC_DEFAULT_BASECOLOR; context.draw_color = 0x000000; // NOTE(toni): We can just straight up use the "right" and "bottom" // variables because the x and y position are always gonna be zero anyways. CDrawUtils::FillRectangle3D( &context, 0, 0, popup->menu_size.cx, popup->menu_size.cy, RECT_RAISED ); // Item positions int xPos = 3, yPos = 3; for (int i = 0; i < List_GetCount(popup->menu_items); ++i) { HMENUITEM item = (HMENUITEM)List_Get(popup->menu_items, i); switch (item->item_style & CPM_ITEM_TYPEMASK) { case CPM_ITEM_ICONTEXT: { // TODO(toni): Implement! } case CPM_ITEM_TEXT: { LPCPM_ITEM_EXTRADATA_TEXT text_data = (LPCPM_ITEM_EXTRADATA_TEXT)item->item_extradata; if (!text_data->item_text) break; int text_x = xPos + 16, text_y = yPos + 3; // Selecting the correct font to draw SelectObject( hdc, (item->item_style & CPM_ITEM_DEFAULT) ? popup->menu_item_font_default : popup->menu_item_font ); if ((item->item_style & CPM_ITEM_STATEMASK) == CPM_ITEM_STATE_SELECTED) { context.fill_color = 0x800000; context.draw_color = 0xFFFFFF; CDrawUtils::FillSolidRectangle( &context, xPos, yPos, popup->menu_size.cx - 6, item->item_size.cy ); } else if ((item->item_style & CPM_ITEM_STATEMASK) == CPM_ITEM_STATE_DISABLED) { context.fill_color = CLASSIC_DEFAULT_BASECOLOR; context.draw_color = 0xFFFFFF; CDrawUtils::DrawString( &context, text_data->item_text, text_x + 1, text_y + 1 ); context.draw_color = 0x848284; } else { context.fill_color = CLASSIC_DEFAULT_BASECOLOR; context.draw_color = 0x000000; } SetBkMode(hdc, TRANSPARENT); CDrawUtils::DrawString( &context, text_data->item_text, text_x, text_y ); SetBkMode(hdc, OPAQUE); } break; case CPM_ITEM_SEPARATOR: { context.fill_color = 0x848284; CDrawUtils::FillSolidRectangle(&context, xPos + 1, yPos + 3, popup->menu_size.cx - 8, 1); context.fill_color = 0xFFFFFF; CDrawUtils::FillSolidRectangle(&context, xPos + 1, yPos + 4, popup->menu_size.cx - 8, 1); } break; default: break; // We should never even get here } yPos += item->item_size.cy; } EndPaint(hWnd, &paintstruct); } break; case WM_MOUSEMOVE: { int mx = (int)((short)LOWORD(lParam)), my = (int)((short)HIWORD(lParam)); // Initial item positions int xPos = 3, yPos = 3; bool flags_changed = false; RECT rect_deselected = { 0, 0, 0, 0 }, rect_selected = { 0, 0, 0, 0 }; for (int i = 0; i < List_GetCount(popup->menu_items); ++i) { HMENUITEM item = (HMENUITEM)List_Get(popup->menu_items, i); // Skipping Separators and disabled items... if (((item->item_style & CPM_ITEM_TYPEMASK) == CPM_ITEM_SEPARATOR) || ((item->item_style & CPM_ITEM_STATEMASK) == CPM_ITEM_STATE_DISABLED)) { yPos += item->item_size.cy; continue; } if ((item->item_style & CPM_ITEM_STATEMASK) == CPM_ITEM_STATE_SELECTED) { // Remember: Border is 3 pixels, and width always means "double the value dude!" if (!IsPointInArea(mx, my, xPos, yPos, popup->menu_size.cx - 6, item->item_size.cy)) { // If previous items are still selected, // even though the mouse isn't over it anymore, // just deselect them item->item_style &= ~CPM_ITEM_STATE_SELECTED; // Marking the area that has to be redrawn // // NOTE(toni): There only should ever be exactly // 1 menu item selected at the same time. // So we only have to care about this one area. rect_deselected.left = xPos; rect_deselected.top = yPos; rect_deselected.right = MAKECOORDINATE(xPos, popup->menu_size.cx - 6); rect_deselected.bottom = MAKECOORDINATE(yPos, item->item_size.cy); flags_changed = true; } } else { if (IsPointInArea(mx, my, xPos, yPos, popup->menu_size.cx - 6, item->item_size.cy)) { // Select the current item item->item_style |= CPM_ITEM_STATE_SELECTED; // Marking the area that has to be redrawn rect_selected.left = xPos; rect_selected.top = yPos; rect_selected.right = MAKECOORDINATE(xPos, popup->menu_size.cx - 6); rect_selected.bottom = MAKECOORDINATE(yPos, item->item_size.cy); flags_changed = true; } } yPos += item->item_size.cy; } if (flags_changed) { if ((rect_deselected.left > 0) && (rect_deselected.top > 0) && (rect_deselected.right > 0) && (rect_deselected.bottom > 0)) RedrawWindow(hWnd, &rect_deselected, NULL, RDW_INVALIDATE); if ((rect_selected.left > 0) && (rect_selected.top > 0) && (rect_selected.right > 0) && (rect_selected.bottom > 0)) RedrawWindow(hWnd, &rect_selected, NULL, RDW_INVALIDATE); } } break; case WM_LBUTTONUP: case WM_RBUTTONUP: { for (int i = 0; i < List_GetCount(popup->menu_items); ++i) { HMENUITEM item = (HMENUITEM)List_Get(popup->menu_items, i); if ((item->item_style & CPM_ITEM_STATEMASK) == CPM_ITEM_STATE_SELECTED) { // Notify the menu procedure (if there is one) // that the user clicked on a menu item! if (popup->menu_proc) { CPM_ITEMINFO info = { item, i }; popup->menu_proc(popup, CPM_ITEMSELECTED, &info); } DestroyWindow(hWnd); break; } } } break; case WM_ACTIVATE: { // If our little popup menu gets thrown into the background // just destroy it... if (!wParam) DestroyWindow(hWnd); } break; case WM_DESTROY: { // Before we deallocate, we have to notify the Menu Procedure. // Because maybe the user wants to access the Menu items // before they're gone. // (if there even is one) if (popup->menu_proc) popup->menu_proc(popup, CPM_DESTROY, NULL); // Destroying all the Menu items // we don't need them anymore after this popup menu has been closed. for (int i = 0; i < List_GetCount(popup->menu_items); ++i) { HMENUITEM item = (HMENUITEM)List_Get(popup->menu_items, i); DestroyMenuItem(item); } PostQuitMessage(0); } break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; }