STATIC控件无法接收WM_MOUSEMOVE,WM_LBUTTONDOWN,WM_LBUTTONUP的问题

探讨了在用户点击或双击控件时,静态控件缺少SS_NOTIFY样式导致消息发送给父窗口的原因及解决方案。

发现这些消息都发送给了父窗口,那么说明STATIC控件缺少一个样式,是SS_NOTIFY,这一点在MSDN上无法得到,SS_NOTIFY的说明为:

SS_NOTIFY   Sends the parent window STN_CLICKED, STN_DBLCLK, STN_DISABLE, and STN_ENABLE notification messages when the user clicks or double-clicks the control. 

貌似SS_NOTIFY跟这三个消息没什么关系,但实际上有,验证属实。


#include <windows.h> #include "GUI.H" #include "DIALOG.h" #include "LISTVIEW.h" #include "GUI_SIM_Win32.h" #include "LCD_SIM.H" #include "gdi.h" #include "gdi_draw.h" HWND ghWndMain = NULL; int is_main = 0; int select_num = 0; #define ID_BUTTON_0 (GUI_ID_USER + 0x00) #define ID_LISTVIEW_0 (GUI_ID_USER + 0x01) #define ID_WINDOW_0 (GUI_ID_USER + 0x02) static const GUI_WIDGET_CREATE_INFO _aDialogCreate[] = { {WINDOW_CreateIndirect, "MainPanel", ID_WINDOW_0, 0, 0, 800, 480, 0, 0x0, 0 }, {BUTTON_CreateIndirect, "Button", ID_BUTTON_0, 40, 420, 60, 15, 0, 0x0, 0 }, {LISTVIEW_CreateIndirect, "Listview", ID_LISTVIEW_0, 0, 50, 400, 300,0, 0x0, 0 }, }; static const char* main_text[][2] = { { "1.", "END" }, { "2.", "SYSTEM BACKUP AND DATA EXPORT" }, { "3.", "SYSTEM RESTORE AND DATA IMPORT" }, { "4.", "SYSTEM UPDATE" }, { "5.", "NVEME DATA UTILITY" }, { "6.", "FRAM DATA UTILITY" }, { "7.", "MEMORY FORMAT" }, { "8.", "FROM DATA UTILITY" }, { "9.", "BOOT SCREEN" }, { "10.", "AUTH" } }; static const char* system_backup_text[][2] = { { "1.", "END" }, { "2.", "BACKUP CNC (*.BAK)" }, { "3.", "EXPORT CNC PROGRAM (PRG.BIN)" }, { "4.", "EXPORT PLC LADDER (LADDER.ZIP)" }, }; static const char* system_restore_text[][2] = { { "1.", "END" }, { "2.", "RESTORE CNC (*.BAK)" }, { "3.", "IMPORT CNC PROGRAM (PRG.BIN)" }, { "4.", "IMPORT PLC LADDER (LADDER.ZIP)" }, }; static const char* system_update_text[][2] = { { "1.", "END" }, }; static const char* nvmem_data_text[][2] = { { "1.", "END" }, { "2.", "BACKUP (CNC -> EXTERNAL MEMORY)" }, { "3.", "RESTORE (EXTERNAL MEMORY -> CNC)" }, { "4.", "RESTORE (AUTO BACKUP -> CNC)" }, { "5.", "FORMAT" }, }; static const char* fram_data_text[][2] = { { "1.", "END" }, { "2.", "BACKUP FRAM (CNC -> EXTERNAL MEMORY)" }, }; static const char* memory_format_text[][2] = { { "1.", "END" }, { "2.", "EXTERNAL MEMORY SD" }, { "3.", "EXTERNAL MEMORY USB" }, { "4.", "CNC PROG MEMORY" }, }; static const char* from_data_text[][2] = { { "1.", "END" }, { "2.", "BACKUP INTERNAL MEMORY (CNC -> EXTERNAL MEMORY)" }, }; static const char* boot_screen_text[][2] = { { "1.", "END" }, { "2.", "BOOT SCREEN DISPLAY MODE :" }, { "3.", "BOOT SCREEN PREVIEW" }, }; static const char* auth_text[][2] = { { "1.", "END" }, { "2.", "PASSWORD :" }, { "3.", "LOGIN" }, }; static void _select_main (int Sel, WM_HWIN hItem) { select_num = Sel; switch (Sel) { case 0: break; case 1: for (int i = 0; i < GUI_COUNTOF (system_backup_text); i++) { LISTVIEW_AddRow (hItem, NULL); LISTVIEW_SetItemText (hItem, 0, i, system_backup_text[i][0]); LISTVIEW_SetItemText (hItem, 1, i, system_backup_text[i][1]); } break; case 2: for (int i = 0; i < GUI_COUNTOF (system_restore_text); i++) { LISTVIEW_AddRow (hItem, NULL); LISTVIEW_SetItemText (hItem, 0, i, system_restore_text[i][0]); LISTVIEW_SetItemText (hItem, 1, i, system_restore_text[i][1]); } break; case 3: for (int i = 0; i < GUI_COUNTOF (system_update_text); i++) { LISTVIEW_AddRow (hItem, NULL); LISTVIEW_SetItemText (hItem, 0, i, system_update_text[i][0]); LISTVIEW_SetItemText (hItem, 1, i, system_update_text[i][1]); } break; case 4: for (int i = 0; i < GUI_COUNTOF (nvmem_data_text); i++) { LISTVIEW_AddRow (hItem, NULL); LISTVIEW_SetItemText (hItem, 0, i, nvmem_data_text[i][0]); LISTVIEW_SetItemText (hItem, 1, i, nvmem_data_text[i][1]); } break; case 5: for (int i = 0; i < GUI_COUNTOF (fram_data_text); i++) { LISTVIEW_AddRow (hItem, NULL); LISTVIEW_SetItemText (hItem, 0, i, fram_data_text[i][0]); LISTVIEW_SetItemText (hItem, 1, i, fram_data_text[i][1]); } break; case 6: for (int i = 0; i < GUI_COUNTOF (memory_format_text); i++) { LISTVIEW_AddRow (hItem, NULL); LISTVIEW_SetItemText (hItem, 0, i, memory_format_text[i][0]); LISTVIEW_SetItemText (hItem, 1, i, memory_format_text[i][1]); } break; case 7: for (int i = 0; i < GUI_COUNTOF (from_data_text); i++) { LISTVIEW_AddRow (hItem, NULL); LISTVIEW_SetItemText (hItem, 0, i, from_data_text[i][0]); LISTVIEW_SetItemText (hItem, 1, i, from_data_text[i][1]); } break; case 8: for (int i = 0; i < GUI_COUNTOF (boot_screen_text); i++) { LISTVIEW_AddRow (hItem, NULL); LISTVIEW_SetItemText (hItem, 0, i, boot_screen_text[i][0]); LISTVIEW_SetItemText (hItem, 1, i, boot_screen_text[i][1]); } break; case 9: for (int i = 0; i < GUI_COUNTOF (auth_text); i++) { LISTVIEW_AddRow (hItem, NULL); LISTVIEW_SetItemText (hItem, 0, i, auth_text[i][0]); LISTVIEW_SetItemText (hItem, 1, i, auth_text[i][1]); } break; } } static void _select_next (int Sel, WM_HWIN hItem) { if (Sel == 1) { for (int i = 0; i < GUI_COUNTOF (main_text); i++) { LISTVIEW_AddRow (hItem, NULL); LISTVIEW_SetItemText (hItem, 0, i, main_text[i][0]); LISTVIEW_SetItemText (hItem, 1, i, main_text[i][1]); } } else if (Sel == 2) { switch (select_num) { } } else if (Sel == 3) { switch (select_num) { } } else if (Sel == 4) { switch (select_num) { } } else if (Sel == 5) { switch (select_num) { } } else if (Sel == 6) { switch (select_num) { } } } static void _cbDialog (WM_MESSAGE* pMsg) { WM_HWIN hItem; int NCode = 0; int Id; HWND hListview; switch (pMsg->MsgId) { case WM_INIT_DIALOG: hItem = WM_GetDialogItem (pMsg->hWin, ID_LISTVIEW_0); LISTVIEW_AddColumn (hItem, 20, "1", GUI_TA_LEFT); LISTVIEW_AddColumn (hItem, 280, "2", GUI_TA_LEFT); LISTVIEW_SetHeaderHeight (hItem, 0); LISTVIEW_SetGridVis (hItem, 0); int FontHeight = GUI_GetFontDistY (); WIDGET_SetEffect (hItem, &WIDGET_Effect_None); LISTVIEW_SetBkColor (hItem, LISTVIEW_CI_UNSEL, GUI_WHITE); LISTVIEW_SetBkColor (hItem, LISTVIEW_CI_SEL, GUI_BLUE); LISTVIEW_SetTextColor (hItem, LISTVIEW_CI_UNSEL, GUI_BLACK); LISTVIEW_SetTextColor (hItem, LISTVIEW_CI_SEL, GUI_WHITE); LISTVIEW_SetRowHeight (hItem, FontHeight + 13); LISTVIEW_SetFont (hItem, GUI_FONT_16_ASCII); for (int i = 0; i < GUI_COUNTOF (main_text); i++) { LISTVIEW_AddRow (hItem, NULL); LISTVIEW_SetItemText (hItem, 0, i, main_text[i][0]); LISTVIEW_SetItemText (hItem, 1, i, main_text[i][1]); } LISTVIEW_SetSel (hItem, 0); WM_SetFocus (hItem); hItem = WM_GetDialogItem (pMsg->hWin, ID_BUTTON_0); BUTTON_SetFont (hItem, GUI_FONT_13_ASCII); BUTTON_SetText (hItem, "[SELECT]"); BUTTON_SetFrameColor (hItem, GUI_WHITE); BUTTON_SetBkColor (hItem, BUTTON_CI_PRESSED, GUI_WHITE); BUTTON_SetBkColor (hItem, BUTTON_CI_UNPRESSED, GUI_WHITE); BUTTON_SetFocusColor (hItem, GUI_WHITE); WM_SetFocus (hItem); WM_InvalidateWindow (pMsg->hWin); case WM_PAINT: GUI_SetBkColor (GUI_WHITE); GUI_Clear (); const GUI_FONT* pOldFont = GUI_GetFont (); GUI_SetFont (&GUI_Font32B_ASCII); GUI_SetColor (GUI_BLACK); GUI_SetTextMode (GUI_TM_NORMAL); GUI_DispStringAt ("SYSTEM MAINTAIN MAIN MENU", 0, 0); GUI_SetFont (pOldFont); break; case WM_NOTIFY_PARENT: Id = WM_GetId (pMsg->hWinSrc); NCode = pMsg->Data.v; switch (Id) { case ID_LISTVIEW_0: switch (NCode) { case WM_NOTIFICATION_CLICKED: break; case WM_NOTIFICATION_RELEASED: break; case WM_NOTIFICATION_SEL_CHANGED: break; } break; case ID_BUTTON_0: switch (NCode) { case WM_NOTIFICATION_CLICKED: break; case WM_NOTIFICATION_RELEASED: hListview = WM_GetDialogItem (pMsg->hWin, ID_LISTVIEW_0); int Sel = LISTVIEW_GetSel (hListview); if (Sel < 0 || Sel > 12) break; LISTVIEW_DeleteAllRows (hListview); (is_main == 0) ? _select_main (Sel, hListview) : _select_next (Sel, hListview); LISTVIEW_SetSel (hListview, 0); break; default: WM_DefaultProc (pMsg); return; } break; } break; default: WM_DefaultProc (pMsg); break; } } static HANDLE ghGUIReady = NULL; WM_HWIN CreateFramewin (void) { WM_HWIN hWin; hWin = GUI_CreateDialogBox (_aDialogCreate, GUI_COUNTOF (_aDialogCreate), _cbDialog, WM_HBKWIN, 0, 0); return hWin; } void MainTask (void) { WaitForSingleObject (ghGUIReady, INFINITE); Sleep (100); BUTTON_SetDefaultSkinClassic (); WM_SetCreateFlags (WM_CF_MEMDEV); GUI_SetBkColor (GUI_WHITE); GUI_Clear (); CreateFramewin (); while (1) { GUI_Delay (50); } } DWORD WINAPI MYTASK (LPVOID lpParam) { MainTask (); return 0; } LRESULT CALLBACK WndProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { HDC hdc; PAINTSTRUCT ps; RECT rect; static int counter = 0; switch (msg) { case WM_PAINT: BeginPaint (hwnd, &ps); RefreshDrawArea (); EndPaint (hwnd, &ps); break; case WM_DESTROY: PostQuitMessage (0); break; case WM_MOUSEMOVE: { int x = LOWORD (lParam); int y = HIWORD (lParam); if (msg == WM_LBUTTONDOWN) { GUI_PID_StoreState (&(GUI_PID_STATE) { 1, x, y, 0 }); } else if (msg == WM_LBUTTONUP) { GUI_PID_StoreState (&(GUI_PID_STATE) { 0, x, y, 0 }); } else if (msg == WM_MOUSEMOVE) { GUI_PID_StoreState (&(GUI_PID_STATE) { wParam& MK_LBUTTON ? 1 : 0, x, y, 0 }); } } break; default: return DefWindowProc (hwnd, msg, wParam, lParam); } return 0; } int APIENTRY WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { UNREFERENCED_PARAMETER (hPrevInstance); UNREFERENCED_PARAMETER (lpCmdLine); SIM_GUI_Enable (); GUI_Init (); const char CLASS_NAME[] = "MyGDIWindowClass"; WNDCLASSEX wc = { 0 }; wc.cbSize = sizeof (WNDCLASSEX); wc.lpfnWndProc = WndProc; // 消息处理函数 wc.hInstance = hInstance; wc.lpszClassName = CLASS_NAME; wc.hCursor = LoadCursor (NULL, IDC_ARROW); // 默认箭头光标 wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); // 初始背景(会被 WM_PAINT 覆盖) wc.style = CS_HREDRAW | CS_VREDRAW; // 大小改变时重绘 RegisterClassEx (&wc); HWND hwnd = CreateWindow ( CLASS_NAME, // 类名 L"123", // 窗口标题 WS_OVERLAPPEDWINDOW| WS_CLIPCHILDREN |WS_VISIBLE, // 窗口样式 0, 0, // x, y 位置 800,480, // 宽高 NULL, // 父窗口(无) NULL, // 菜单(无) hInstance, // 实例句柄 NULL // 额外参数 ); if (!hwnd) return 0; InitDraw (hwnd); ShowWindow (hwnd, nCmdShow); UpdateWindow (hwnd); InvalidateRect (hwnd, NULL, TRUE); UpdateWindow (hwnd); SetEvent (ghGUIReady); CreateThread (NULL, 0, MYTASK, NULL, 0, NULL); MSG msg; while (GetMessage (&msg, NULL, 0, 0)) { TranslateMessage (&msg); DispatchMessage (&msg); } return (int)msg.wParam; } 光标只停留在第一行,点击也没有,按键也无法点击
10-18
#include <windows.h> #include "GUI.H" #include "DIALOG.h" #include "LISTVIEW.h" #include "GUI_SIM_Win32.h" #include "LCD_SIM.H" #include "gdi.h" #include "gdi_draw.h" HWND ghWndMain = NULL; int is_main = 0; int select_num = 0; #define ID_BUTTON_0 (GUI_ID_USER + 0x00) #define ID_LISTVIEW_0 (GUI_ID_USER + 0x01) #define ID_WINDOW_0 (GUI_ID_USER + 0x02) static const GUI_WIDGET_CREATE_INFO _aDialogCreate[] = { {WINDOW_CreateIndirect, "MainPanel", ID_WINDOW_0, 0, 0, 800, 480, 0, 0x0, 0 }, {BUTTON_CreateIndirect, "Button", ID_BUTTON_0, 40, 420, 60, 15, 0, 0x0, 0 }, {LISTVIEW_CreateIndirect, "Listview", ID_LISTVIEW_0, 0, 50, 400, 300,0, 0x0, 0 }, }; static const char* main_text[][2] = { { "1.", "END" }, { "2.", "SYSTEM BACKUP AND DATA EXPORT" }, { "3.", "SYSTEM RESTORE AND DATA IMPORT" }, { "4.", "SYSTEM UPDATE" }, { "5.", "NVEME DATA UTILITY" }, { "6.", "FRAM DATA UTILITY" }, { "7.", "MEMORY FORMAT" }, { "8.", "FROM DATA UTILITY" }, { "9.", "BOOT SCREEN" }, { "10.", "AUTH" } }; static const char* system_backup_text[][2] = { { "1.", "END" }, { "2.", "BACKUP CNC (*.BAK)" }, { "3.", "EXPORT CNC PROGRAM (PRG.BIN)" }, { "4.", "EXPORT PLC LADDER (LADDER.ZIP)" }, }; static const char* system_restore_text[][2] = { { "1.", "END" }, { "2.", "RESTORE CNC (*.BAK)" }, { "3.", "IMPORT CNC PROGRAM (PRG.BIN)" }, { "4.", "IMPORT PLC LADDER (LADDER.ZIP)" }, }; static const char* system_update_text[][2] = { { "1.", "END" }, }; static const char* nvmem_data_text[][2] = { { "1.", "END" }, { "2.", "BACKUP (CNC -> EXTERNAL MEMORY)" }, { "3.", "RESTORE (EXTERNAL MEMORY -> CNC)" }, { "4.", "RESTORE (AUTO BACKUP -> CNC)" }, { "5.", "FORMAT" }, }; static const char* fram_data_text[][2] = { { "1.", "END" }, { "2.", "BACKUP FRAM (CNC -> EXTERNAL MEMORY)" }, }; static const char* memory_format_text[][2] = { { "1.", "END" }, { "2.", "EXTERNAL MEMORY SD" }, { "3.", "EXTERNAL MEMORY USB" }, { "4.", "CNC PROG MEMORY" }, }; static const char* from_data_text[][2] = { { "1.", "END" }, { "2.", "BACKUP INTERNAL MEMORY (CNC -> EXTERNAL MEMORY)" }, }; static const char* boot_screen_text[][2] = { { "1.", "END" }, { "2.", "BOOT SCREEN DISPLAY MODE :" }, { "3.", "BOOT SCREEN PREVIEW" }, }; static const char* auth_text[][2] = { { "1.", "END" }, { "2.", "PASSWORD :" }, { "3.", "LOGIN" }, }; static void _select_main (int Sel, WM_HWIN hItem) { select_num = Sel; switch (Sel) { case 0: break; case 1: for (int i = 0; i < GUI_COUNTOF (system_backup_text); i++) { LISTVIEW_AddRow (hItem, NULL); LISTVIEW_SetItemText (hItem, 0, i, system_backup_text[i][0]); LISTVIEW_SetItemText (hItem, 1, i, system_backup_text[i][1]); } break; case 2: for (int i = 0; i < GUI_COUNTOF (system_restore_text); i++) { LISTVIEW_AddRow (hItem, NULL); LISTVIEW_SetItemText (hItem, 0, i, system_restore_text[i][0]); LISTVIEW_SetItemText (hItem, 1, i, system_restore_text[i][1]); } break; case 3: for (int i = 0; i < GUI_COUNTOF (system_update_text); i++) { LISTVIEW_AddRow (hItem, NULL); LISTVIEW_SetItemText (hItem, 0, i, system_update_text[i][0]); LISTVIEW_SetItemText (hItem, 1, i, system_update_text[i][1]); } break; case 4: for (int i = 0; i < GUI_COUNTOF (nvmem_data_text); i++) { LISTVIEW_AddRow (hItem, NULL); LISTVIEW_SetItemText (hItem, 0, i, nvmem_data_text[i][0]); LISTVIEW_SetItemText (hItem, 1, i, nvmem_data_text[i][1]); } break; case 5: for (int i = 0; i < GUI_COUNTOF (fram_data_text); i++) { LISTVIEW_AddRow (hItem, NULL); LISTVIEW_SetItemText (hItem, 0, i, fram_data_text[i][0]); LISTVIEW_SetItemText (hItem, 1, i, fram_data_text[i][1]); } break; case 6: for (int i = 0; i < GUI_COUNTOF (memory_format_text); i++) { LISTVIEW_AddRow (hItem, NULL); LISTVIEW_SetItemText (hItem, 0, i, memory_format_text[i][0]); LISTVIEW_SetItemText (hItem, 1, i, memory_format_text[i][1]); } break; case 7: for (int i = 0; i < GUI_COUNTOF (from_data_text); i++) { LISTVIEW_AddRow (hItem, NULL); LISTVIEW_SetItemText (hItem, 0, i, from_data_text[i][0]); LISTVIEW_SetItemText (hItem, 1, i, from_data_text[i][1]); } break; case 8: for (int i = 0; i < GUI_COUNTOF (boot_screen_text); i++) { LISTVIEW_AddRow (hItem, NULL); LISTVIEW_SetItemText (hItem, 0, i, boot_screen_text[i][0]); LISTVIEW_SetItemText (hItem, 1, i, boot_screen_text[i][1]); } break; case 9: for (int i = 0; i < GUI_COUNTOF (auth_text); i++) { LISTVIEW_AddRow (hItem, NULL); LISTVIEW_SetItemText (hItem, 0, i, auth_text[i][0]); LISTVIEW_SetItemText (hItem, 1, i, auth_text[i][1]); } break; } } static void _select_next (int Sel, WM_HWIN hItem) { if (Sel == 1) { for (int i = 0; i < GUI_COUNTOF (main_text); i++) { LISTVIEW_AddRow (hItem, NULL); LISTVIEW_SetItemText (hItem, 0, i, main_text[i][0]); LISTVIEW_SetItemText (hItem, 1, i, main_text[i][1]); } } else if (Sel == 2) { switch (select_num) { } } else if (Sel == 3) { switch (select_num) { } } else if (Sel == 4) { switch (select_num) { } } else if (Sel == 5) { switch (select_num) { } } else if (Sel == 6) { switch (select_num) { } } } static void _cbDialog (WM_MESSAGE* pMsg) { WM_HWIN hItem; int NCode = 0; int Id; int Sel; HWND hListview; switch (pMsg->MsgId) { case WM_INIT_DIALOG: hItem = WM_GetDialogItem (pMsg->hWin, ID_LISTVIEW_0); LISTVIEW_AddColumn (hItem, 20, "1", GUI_TA_LEFT); LISTVIEW_AddColumn (hItem, 280, "2", GUI_TA_LEFT); LISTVIEW_SetHeaderHeight (hItem, 0); LISTVIEW_SetGridVis (hItem, 0); int FontHeight = GUI_GetFontDistY (); WIDGET_SetEffect (hItem, &WIDGET_Effect_None); LISTVIEW_SetBkColor (hItem, LISTVIEW_CI_UNSEL, GUI_WHITE); LISTVIEW_SetBkColor (hItem, LISTVIEW_CI_SEL, GUI_BLUE); LISTVIEW_SetTextColor (hItem, LISTVIEW_CI_UNSEL, GUI_BLACK); LISTVIEW_SetTextColor (hItem, LISTVIEW_CI_SEL, GUI_WHITE); LISTVIEW_SetRowHeight (hItem, FontHeight + 13); LISTVIEW_SetFont (hItem, GUI_FONT_16_ASCII); for (int i = 0; i < GUI_COUNTOF (main_text); i++) { LISTVIEW_AddRow (hItem, NULL); LISTVIEW_SetItemText (hItem, 0, i, main_text[i][0]); LISTVIEW_SetItemText (hItem, 1, i, main_text[i][1]); } LISTVIEW_SetSel (hItem, 0); WM_SetFocus (hItem); hItem = WM_GetDialogItem (pMsg->hWin, ID_BUTTON_0); BUTTON_SetFont (hItem, GUI_FONT_13_ASCII); BUTTON_SetText (hItem, "[SELECT]"); BUTTON_SetFrameColor (hItem, GUI_WHITE); BUTTON_SetBkColor (hItem, BUTTON_CI_PRESSED, GUI_WHITE); BUTTON_SetBkColor (hItem, BUTTON_CI_UNPRESSED, GUI_WHITE); BUTTON_SetFocusColor (hItem, GUI_WHITE); WM_InvalidateWindow (pMsg->hWin); break; case WM_PAINT: GUI_SetBkColor (GUI_WHITE); GUI_Clear (); const GUI_FONT* pOldFont = GUI_GetFont (); GUI_SetFont (&GUI_Font32B_ASCII); GUI_SetColor (GUI_BLACK); GUI_SetTextMode (GUI_TM_NORMAL); GUI_DispStringAt ("SYSTEM MAINTAIN MAIN MENU", 0, 0); GUI_SetFont (pOldFont); break; case WM_NOTIFY_PARENT: Id = WM_GetId (pMsg->hWinSrc); NCode = pMsg->Data.v; switch (Id) { case ID_LISTVIEW_0: switch (NCode) { case WM_NOTIFICATION_CLICKED: break; case WM_NOTIFICATION_RELEASED: break; case WM_NOTIFICATION_SEL_CHANGED: Sel = LISTVIEW_GetSel (WM_GetDialogItem (pMsg->hWin, ID_LISTVIEW_0)); if (Sel >= 0) { select_num = Sel; } break; break; } break; case ID_BUTTON_0: switch (NCode) { case WM_NOTIFICATION_CLICKED: break; case WM_NOTIFICATION_RELEASED: hListview = WM_GetDialogItem (pMsg->hWin, ID_LISTVIEW_0); Sel = LISTVIEW_GetSel (hListview); if (Sel < 0 || Sel > 12) break; LISTVIEW_DeleteAllRows (hListview); (is_main == 0) ? _select_main (Sel, hListview) : _select_next (Sel, hListview); break; default: WM_DefaultProc (pMsg); return; } break; } break; default: WM_DefaultProc (pMsg); break; } } static HANDLE ghGUIReady = NULL; WM_HWIN CreateFramewin (void) { WM_HWIN hWin; hWin = GUI_CreateDialogBox (_aDialogCreate, GUI_COUNTOF (_aDialogCreate), _cbDialog, WM_HBKWIN, 0, 0); return hWin; } void MainTask (void) { WaitForSingleObject (ghGUIReady, INFINITE); Sleep (100); BUTTON_SetDefaultSkinClassic (); WM_SetCreateFlags (WM_CF_MEMDEV); GUI_SetBkColor (GUI_WHITE); GUI_Clear (); CreateFramewin (); while (1) { GUI_Delay (10); } } DWORD WINAPI MYTASK (LPVOID lpParam) { MainTask (); return 0; } LRESULT CALLBACK WndProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { HDC hdc; PAINTSTRUCT ps; RECT rect; RECT clientRect; static int counter = 0; switch (msg) { case WM_PAINT: BeginPaint (hwnd, &ps); RefreshDrawArea (); EndPaint (hwnd, &ps); break; case WM_DESTROY: PostQuitMessage (0); break; case WM_LBUTTONDOWN: GetClientRect (hwnd, &clientRect); int x = LOWORD (lParam); int y = HIWORD (lParam); GUI_PID_StoreState (&(GUI_PID_STATE) { 1, x, y, 0 }); InvalidateRect (hwnd, NULL, TRUE); break; case WM_LBUTTONUP: { GetClientRect (hwnd, &clientRect); int x = LOWORD (lParam); int y = HIWORD (lParam); GUI_PID_StoreState (&(GUI_PID_STATE) { 0, x, y, 0 }); InvalidateRect (hwnd, NULL, TRUE); break; } case WM_MOUSEMOVE: { GetClientRect (hwnd, &clientRect); int x = LOWORD (lParam); int y = HIWORD (lParam); int Pressed = (wParam & MK_LBUTTON) ? 1 : 0; GUI_PID_StoreState (&(GUI_PID_STATE) { Pressed, x, y, 0 }); if (Pressed) { InvalidateRect (hwnd, NULL, TRUE); } break; } case WM_DPICHANGED: { WORD dpi = HIWORD (wParam); RECT* const newRect = (RECT*)lParam; SetWindowPos (hwnd, NULL, newRect->left, newRect->top, newRect->right - newRect->left, newRect->bottom - newRect->top, SWP_NOZORDER | SWP_NOACTIVATE); break; } case WM_ERASEBKGND: return 1; default: return DefWindowProc (hwnd, msg, wParam, lParam); } return 0; } int APIENTRY WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { UNREFERENCED_PARAMETER (hPrevInstance); UNREFERENCED_PARAMETER (lpCmdLine); ghGUIReady = CreateEvent (NULL, TRUE, FALSE, NULL); SIM_GUI_Enable (); GUI_Init (); const char CLASS_NAME[] = "MyGDIWindowClass"; WNDCLASSEX wc = { 0 }; wc.cbSize = sizeof (WNDCLASSEX); wc.lpfnWndProc = WndProc; // 消息处理函数 wc.hInstance = hInstance; wc.lpszClassName = CLASS_NAME; wc.hCursor = LoadCursor (NULL, IDC_ARROW); // 默认箭头光标 wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); // 初始背景(会被 WM_PAINT 覆盖) wc.style = CS_HREDRAW | CS_VREDRAW; // 大小改变时重绘 RegisterClassEx (&wc); RECT rect = { 0, 0, 800, 480 }; // 期望的客户区大小 AdjustWindowRect (&rect, WS_OVERLAPPEDWINDOW, FALSE); int width = rect.right - rect.left; int height = rect.bottom - rect.top; HWND hwnd = CreateWindow ( CLASS_NAME, L"System Maintenance", WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, // 位置 width, height, NULL, NULL, hInstance, NULL); if (!hwnd) return 0; HDC screenDC = GetDC (NULL); int dpiX = GetDeviceCaps (screenDC, LOGPIXELSX); int dpiY = GetDeviceCaps (screenDC, LOGPIXELSY); ReleaseDC (NULL, screenDC); InitDraw (hwnd); ShowWindow (hwnd, nCmdShow); UpdateWindow (hwnd); InvalidateRect (hwnd, NULL, TRUE); UpdateWindow (hwnd); SetEvent (ghGUIReady); CreateThread (NULL, 0, MYTASK, NULL, 0, NULL); MSG msg; while (GetMessage (&msg, NULL, 0, 0)) { TranslateMessage (&msg); DispatchMessage (&msg); } CloseHandle (ghGUIReady); return (int)msg.wParam; } 生成的列表无法点击,要么无反应要么高亮其它位置,按键也无反应
最新发布
10-18
请根据我提供的滚动条控件源码,重构一个更高效的控件给我 #ifndef _SCROLL_BAR_H_ #define _SCROLL_BAR_H_ #include "BaseWnd/CBaseWnd.h" class ScrollBar : public MFC::CBaseWnd { public: ScrollBar(); ~ScrollBar(); BOOL Create(const int _iBar, const CRect& _Rect, CWnd* _pParent, const int _iArrowFlags = ESB_ENABLE_BOTH, const int _iSpace = 3, const int _iMinSlider = 10); BOOL SetScrollInfo(SCROLLINFO& _refScrollInfo, BOOL _bRedraw = TRUE); BOOL SetScrollPos(int _iPos, BOOL _bRedraw = TRUE); void SetTarget(CWnd* _pTargetWnd); private: int m_iBar; //此滚动条的风格: SB_HORZ = 水平横向滚动条, SB_VERT = 垂直纵向滚动条 int m_iSpace; //滚动条滑块通道两边的空白间隔 int m_iMinSlider; //滑块的最小宽度,不可能无限小吧,滑块过小了肉眼都难看到了 int m_iArrowFlags; //两边是否开启箭头 float m_fRatio; //比率: 如: 滚动条滚动 1pixl, 目标控件该移动多少 pix? 或者反过来,目标控件移动了10pix , 那么滚动条应该移动多少pix? CRect m_rcLTUP; //滚动条(左边/顶部)的箭头范围 3个范围组成完整的滚动条 CRect m_rcScroll; //滚动条通道的范围 3个范围组成完整的滚动条 CRect m_rcRTDN; //滚动条(右边/底部)的箭头范围 3个范围组成完整的滚动条 SCROLLINFO m_infoScroll; //滚动条的信息 这2个info是相互关联依赖 SCROLLBARINFO m_infoScrollBar; //滚动条的滑块信息 这2个info是相互关联依赖 //以下解释2个info的关联性 /* typedef struct tagSCROLLINFO { UINT cbSize; //size of(SCROLLINFO) UINT fMask; //SIF_ALL 即nMin, nMax, nPage, nPos, nTrackPos 5个变量值都得到更改 int nMin; //一般置 0 int nMax; //目标控件的最大可见内容, 比如我的目标控件宽度: 666 pix, 控件内有一行文字内容,此行文字占:977 pix, 那么此行内容就有: 977-666 pix内容是看不到了,那么最大可见内容nMax=977 UINT nPage; //目标控件的宽度: 666 pix, 一般一行文字的最前面和最后面都有一个占1pix的光标,正如我们打字那个光标一样, 666-2pix = 664, 那么nPag = 664 int nPos; //这里我预设为: 29, 最下面会给出这个29的计算方法 int nTrackPos; //这个值是以前旧nPos, 等更新完成后,也会变成29 } SCROLLINFO, FAR* LPSCROLLINFO; */ /* typedef struct tagSCROLLBARINFO { DWORD cbSize; //size of(SCROLLBARINFO) RECT rcScrollBar; //滚动条的全部范围: 我预设此滚动条是: 666*17 pix, 水平横向滚动条,两头带17 pix的箭头按钮 int dxyLineButton; //滚动条2头的箭头宽度: 17pix int xyThumbTop; //滑块左边位于滚动条的位置, 这里是36 pix 这个36 pix和上面的nPos 29pix是有关联性的 int xyThumbBottom; //滑块右边位于滚动条的位置, 这里是465 pix, 那么这个滚动条中间滑块的宽度就是: 465-36 int reserved; //windows预留位置,不用管 DWORD rgstate[CCHILDREN_SCROLLBAR + 1]; //当滚动可见,这里全部为0, 可视状态开关 } SCROLLBARINFO, * PSCROLLBARINFO, * LPSCROLLBARINFO; */ /*  * xyThumbTop = 36 计算出 nPos = 29 : * xyThumbTop-17 = 36-17 = 19pix, 先去除左边箭头的宽度得到真实: 当前滚动条已经滚动的距离 * 计算比率: 滚动条的长度/目标控件的最大可见内容 = (666-(17*2))/977 = 0.6468781 (17*2)是去掉2个箭头距离 * xyThumbTop / 比率 = 19/0.6468781 = 29.37183991 = (int)29 = nPos = 29 * nPos逆向计算xyThumbTop = 29*0.6468781 = 19 * 总结: SCROLLBARINFO信息控制滚动条内部信息,SCROLLINFO控制外部目标控件的信息 */ CRect m_rcSlider; //滚动条内滑块的范围 COLORREF m_clrSlider; //滑块的状态颜色 COLORREF m_clrSlider_Def; //滑块无操作状态下的颜色 COLORREF m_clrSlider_Hover; //鼠标悬停在滑块上面的颜色 COLORREF m_clrSlider_Click; //鼠标左键按下滑块的颜色 BOOL m_bIsTrack; //鼠标触发WM_MOUSEMOVE一次就触发一次鼠标悬停?明显太浪费了,所以这个bIsTrack控制,确保已经触发完成鼠标悬停事件再重置bIsTrack BOOL m_bIsCaptrue; //监视这个控件是不是正在 捕获焦点 中 CPoint m_ptMouseLastPoint; //鼠标移动: 从A点移动到B点, m_ptMouseLastPoint代表A点(存储), B点在WM_MOUSEMOVE事件能得到 int m_iLTUPBtn; //(左边/顶部)箭头的(宽度/长度) int m_iRTDNBtn; //(右边/底部)箭头的(宽度/长度) CRgn m_rgnLTUPBtn; //(左边/顶部)三角形箭头的绘画路径 CRgn m_rgnRTDNBtn; //(右边/底部)三角形箭头的绘画路径 COLORREF m_clrArrow; //箭头的状态颜色 COLORREF m_clrArrow_Def; //箭头无操作状态颜色 COLORREF m_clrArrow_Hover; //鼠标悬停在箭头上的颜色 COLORREF m_clrArrow_Click; //鼠标左键按下箭头的颜色 BOOL m_bIsEnd; //当前滚动条已经达到尽头 CWnd* m_pTargetWnd; //关联的目标控件 float m_fCorrectionLT; //补正(左箭头/顶部箭头)移动距离 float m_fCorrectionRD; //补正(右箭头/底部箭头)移动距离 public: DECLARE_MESSAGE_MAP() afx_msg void OnPaint(); afx_msg void OnMouseMove(UINT nFlags, CPoint point); afx_msg void OnMouseHover(UINT nFlags, CPoint point); afx_msg void OnMouseLeave(); afx_msg void OnLButtonDown(UINT nFlags, CPoint point); afx_msg void OnLButtonUp(UINT nFlags, CPoint point); afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar); afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar); virtual void OnMouseLeave(const CPoint& _point); virtual void OnDragSlider(const CPoint& _point); virtual void OnClickLTUPBtn();//点击了(左箭头/顶部箭头) virtual void OnClickRTDNBtn();//点击了(右箭头/底部箭头) }; #endif#include "ScrollBar.h" ScrollBar::ScrollBar(): m_iBar(0), m_iSpace(0), m_iMinSlider(0), m_iArrowFlags(ESB_ENABLE_BOTH), m_fRatio(0.0f), m_bIsTrack(FALSE), m_bIsCaptrue(FALSE), m_iLTUPBtn(0), m_iRTDNBtn(0), m_bIsEnd(FALSE), m_pTargetWnd(NULL), m_fCorrectionLT(0.0f), m_fCorrectionRD(0.0f) { //初始化一些基本结构 m_rcLTUP = { 0, 0, 0, 0 }; m_rcScroll = {0, 0, 0, 0}; m_rcRTDN = {0, 0, 0, 0}; memset(&m_infoScroll, 0, sizeof m_infoScroll); m_infoScroll.cbSize = sizeof m_infoScroll; memset(&m_infoScrollBar, 0, sizeof m_infoScrollBar); m_infoScrollBar.cbSize = sizeof m_infoScrollBar; m_rcSlider = { 0,0,0,0 }; m_clrSlider_Def = RGB(104, 104, 104); m_clrSlider_Hover = RGB(158, 158, 158); m_clrSlider_Click = RGB(239, 235, 239); m_clrSlider = m_clrSlider_Def; m_ptMouseLastPoint = { 0,0 }; m_clrArrow_Def = RGB(104, 104, 104); m_clrArrow_Hover = RGB(158, 158, 158); m_clrArrow_Click = RGB(239, 235, 239); m_clrArrow = m_clrArrow_Def; } ScrollBar::~ScrollBar() { //箭头路径销毁: windwos要求释放资源 m_rgnLTUPBtn.DeleteObject(); m_rgnRTDNBtn.DeleteObject(); } BOOL ScrollBar::Create(const int _iBar, const CRect& _Rect, CWnd* _pParent, const int _iArrowFlags, const int _iSpace, const int _iMinSlider) { //准备滚动条数据 m_iBar = _iBar; //存储滚动条风格: SB_HORZ=水平横向滚动条; SB_VERT=垂直纵向滚动条 m_iSpace = _iSpace; //存储滚动条滑块两边空白间隔 m_iArrowFlags = _iArrowFlags; //存储滚动条的箭头开关值: 0=两个都开启; 1=(左边/顶部)的箭头关闭; 2=(右边/底部)的箭头关闭; 3=两个都关闭 m_iMinSlider = _iMinSlider; //存储滚动条滑块的最小(宽度/长度),不可能无限短,太短肉眼都看不见了 CRect recWnd = { 0, 0, 0,0 }; if (CBaseWnd::Create("scroll bar", _Rect, _pParent, NULL, WS_CHILD | WS_VISIBLE))//创建控件 { //控件创建成功 m_infoScrollBar.rcScrollBar = {0, 0, _Rect.Width(), _Rect.Height()};//设置滚动条所占此控件的范围,一般是全部 recWnd = m_infoScrollBar.rcScrollBar; switch (_iBar) { case SB_HORZ: m_infoScrollBar.dxyLineButton = _Rect.Height();//如果是水平滚动条, 箭头按钮长度就是控件的宽度 break; case SB_VERT: m_infoScrollBar.dxyLineButton = _Rect.Width();//如果是垂直滚动条, 箭头按钮的宽度就是控件的长度 break; } switch (_iArrowFlags) { case ESB_ENABLE_BOTH://2个箭头都开启 m_iLTUPBtn = m_infoScrollBar.dxyLineButton; m_iRTDNBtn = m_infoScrollBar.dxyLineButton; break; case ESB_DISABLE_LTUP://关闭(左边/顶部)的箭头 m_iLTUPBtn = 0; m_iRTDNBtn = m_infoScrollBar.dxyLineButton; break; case ESB_DISABLE_RTDN://关闭(右边/底部)的箭头 m_iLTUPBtn = m_infoScrollBar.dxyLineButton; m_iRTDNBtn = 0; break; case ESB_DISABLE_BOTH://2个箭头都关闭 m_iLTUPBtn = 0; m_iRTDNBtn = 0; break; } switch (_iBar) { case SB_HORZ: { m_infoScroll.nMax = _Rect.Width();//初始化目标控件里面的内容最大可视范围 m_infoScroll.nPage = _Rect.Width();//初始化目标控件的最大范围 m_rcSlider = { recWnd.left + m_iLTUPBtn, recWnd.top + m_iSpace, recWnd.right - m_iRTDNBtn, recWnd.bottom - m_iSpace };//初始化滑块坐标范围 m_infoScrollBar.xyThumbTop = m_rcSlider.left;//滑块的左边坐标 m_infoScrollBar.xyThumbBottom = m_rcSlider.right;//滑块的右边坐标 CPoint vecPoint[3]; //绘画左边箭头三角形 vecPoint[0] = { m_iSpace+1, m_infoScrollBar.dxyLineButton / 2 }; vecPoint[1] = { m_infoScrollBar.dxyLineButton - m_iSpace*2, m_infoScrollBar.dxyLineButton - m_iSpace }; vecPoint[2] = { m_infoScrollBar.dxyLineButton - m_iSpace*2 , m_iSpace-1 }; m_rgnLTUPBtn.CreatePolygonRgn(vecPoint, 3, WINDING); //绘画右边箭头三角形 vecPoint[0] = {recWnd.Width()-(m_iSpace + 1), m_infoScrollBar.dxyLineButton / 2 }; vecPoint[1] = {recWnd.Width()- (m_infoScrollBar.dxyLineButton - m_iSpace * 2), m_infoScrollBar.dxyLineButton - m_iSpace }; vecPoint[2] = {recWnd.Width() - (m_infoScrollBar.dxyLineButton - m_iSpace * 2), m_iSpace-1 }; m_rgnRTDNBtn.CreatePolygonRgn(vecPoint, 3, WINDING); //分配范围 m_rcLTUP = { recWnd.left, recWnd.top, recWnd.left + m_iLTUPBtn, recWnd.bottom };//左箭头范围 m_rcRTDN = { recWnd.right - m_iRTDNBtn, recWnd.top, recWnd.right, recWnd.bottom };//右箭头范围 m_rcScroll = {recWnd.left+m_iLTUPBtn, recWnd.top, recWnd.right-m_iRTDNBtn, recWnd.bottom};//中间滚动条通道 m_rcSlider = {m_rcScroll.left, m_rcScroll.top+m_iSpace, m_rcScroll.right, m_rcScroll.bottom-m_iSpace}; break; } case SB_VERT: { m_infoScroll.nMax = recWnd.Height();//初始化目标控件里面的内容最大可视范围 m_infoScroll.nPage = recWnd.Height();//初始化目标控件的最大范围 m_rcSlider = {recWnd.left+m_iSpace, recWnd.top+m_iLTUPBtn, recWnd.right-m_iSpace, recWnd.bottom-m_iRTDNBtn};//初始化滑块坐标范围 m_infoScrollBar.xyThumbTop = m_rcSlider.top;//滑块顶部的坐标 m_infoScrollBar.xyThumbBottom = m_rcSlider.bottom;//滑块底部的坐标 CPoint vecPoint[3]; //绘画顶部箭头的三角形 vecPoint[0] = { m_infoScrollBar.dxyLineButton / 2 , m_iSpace }; vecPoint[1] = { m_iSpace-1, m_infoScrollBar.dxyLineButton - m_iSpace * 2 }; vecPoint[2] = { m_infoScrollBar.dxyLineButton - m_iSpace, m_infoScrollBar.dxyLineButton - m_iSpace*2 }; m_rgnLTUPBtn.CreatePolygonRgn(vecPoint, 3, WINDING); //绘画底部箭头的三角形 vecPoint[0] = { m_infoScrollBar.dxyLineButton / 2 , recWnd.Height() - m_iSpace - 1 }; vecPoint[1] = { m_iSpace , recWnd.Height() - m_infoScrollBar.dxyLineButton + m_iSpace * 2 }; vecPoint[2] = { m_infoScrollBar.dxyLineButton - m_iSpace, recWnd.Height() - m_infoScrollBar.dxyLineButton + m_iSpace * 2 }; m_rgnRTDNBtn.CreatePolygonRgn(vecPoint, 3, WINDING); //分配范围 m_rcLTUP = { recWnd.left, recWnd.top, recWnd.right, recWnd.top+m_iLTUPBtn };//上箭头范围 m_rcRTDN = { recWnd.left, recWnd.bottom - m_iRTDNBtn, recWnd.right, recWnd.bottom };//下箭头范围 m_rcScroll = { recWnd.left, recWnd.top + m_iLTUPBtn, recWnd.right, recWnd.bottom - m_iRTDNBtn };//中间滚动条通道 m_rcSlider = {m_rcScroll.left+m_iSpace, m_rcScroll.top, m_rcScroll.right-m_iSpace, m_rcScroll.bottom}; break; } } return TRUE; } return FALSE; } BEGIN_MESSAGE_MAP(ScrollBar, MFC::CBaseWnd) ON_WM_PAINT() ON_WM_MOUSEMOVE() ON_WM_MOUSEHOVER() ON_WM_MOUSELEAVE() ON_WM_LBUTTONDOWN() ON_WM_LBUTTONUP() ON_WM_HSCROLL() ON_WM_VSCROLL() END_MESSAGE_MAP() void ScrollBar::OnPaint() { CPaintDC dc(this); // device context for painting // TODO: 在此处添加消息处理程序代码 // 不为绘图消息调用 CBaseWnd::OnPaint() CBrush brush; brush.CreateSolidBrush(m_clrArrow); m_MemDC.FillSolidRect(m_rcWnd, RGB(62, 62, 66));//背景色 m_MemDC.FillSolidRect(m_rcSlider, m_clrSlider);//滑块色 if(m_iLTUPBtn) m_MemDC.FillRgn(&m_rgnLTUPBtn, &brush); if(m_iRTDNBtn) m_MemDC.FillRgn(&m_rgnRTDNBtn, &brush); brush.DeleteObject(); dc.BitBlt(0, 0, m_rcWnd.Width(), m_rcWnd.Height(), &m_MemDC, 0, 0, SRCCOPY); //更新scroll bar info数据 switch (m_iBar) { case SB_HORZ: m_infoScrollBar.xyThumbTop = m_rcSlider.left; m_infoScrollBar.xyThumbBottom = m_rcSlider.right; break; case SB_VERT: m_infoScrollBar.xyThumbTop = m_rcSlider.top; m_infoScrollBar.xyThumbBottom = m_rcSlider.bottom; break; } } void ScrollBar::OnMouseMove(UINT nFlags, CPoint point) { // TODO: 在此添加消息处理程序代码和/或调用默认值 if (!m_bIsTrack && !m_bIsCaptrue) { m_bIsTrack = TRUE; TRACKMOUSEEVENT tme; tme.cbSize = sizeof(tme); tme.hwndTrack = m_hWnd; tme.dwFlags = TME_LEAVE | TME_HOVER; tme.dwHoverTime = 1;// 鼠标在按钮上停留超过 1ms ,才认为成功 _TrackMouseEvent(&tme); } if (m_bIsCaptrue) { OnDragSlider(point); m_ptMouseLastPoint = point; } CBaseWnd::OnMouseMove(nFlags, point); } void ScrollBar::OnMouseHover(UINT nFlags, CPoint point) { // TODO: 在此添加消息处理程序代码和/或调用默认值 OnMouseLeave(m_ptMouseLastPoint); if (PtInRect(m_rcLTUP, point)) { //鼠标悬停在(左边/顶部)箭头上面 m_clrArrow = m_clrArrow_Hover; InvalidateRect(m_rcLTUP); } else if (PtInRect(m_rcRTDN, point)) { //鼠标悬停在(右边/底部)箭头上面 m_clrArrow = m_clrArrow_Hover; InvalidateRect(m_rcRTDN); } else if (PtInRect(m_rcSlider, point)) { //鼠标悬停在滑块上面 m_clrSlider = m_clrSlider_Hover; InvalidateRect(m_rcSlider); } m_ptMouseLastPoint = point; m_bIsTrack = FALSE; CBaseWnd::OnMouseHover(nFlags, point); } void ScrollBar::OnMouseLeave(const CPoint& _point) { if (PtInRect(m_rcLTUP, _point)) { //鼠标离开(左边/顶部)箭头 m_clrArrow = m_clrArrow_Def; InvalidateRect(m_rcLTUP); } else if (PtInRect(m_rcRTDN, _point)) { //鼠标离开(右边/底部)箭头 m_clrArrow = m_clrArrow_Def; InvalidateRect(m_rcRTDN); } else if (PtInRect(m_rcSlider, _point)) { //鼠标离开滑块 m_clrSlider = m_clrSlider_Def; InvalidateRect(m_rcSlider); } } void ScrollBar::OnMouseLeave() { // TODO: 在此添加消息处理程序代码和/或调用默认值 //鼠标离开控件 m_bIsTrack = FALSE; m_clrSlider = m_clrSlider_Def; m_clrArrow = m_clrArrow_Def; Invalidate(); if (m_bIsCaptrue) { ReleaseCapture(); m_bIsCaptrue = FALSE; } CBaseWnd::OnMouseLeave(); } void ScrollBar::OnLButtonDown(UINT nFlags, CPoint point) { // TODO: 在此添加消息处理程序代码和/或调用默认值 if (PtInRect(m_rcLTUP, point)) { //鼠标左键点击(左边/顶部)箭头 m_clrArrow = m_clrArrow_Click; InvalidateRect(m_rcLTUP); OnClickLTUPBtn(); } else if (PtInRect(m_rcRTDN, point)) { //鼠标左键点击(右边/底部)箭头 m_clrArrow = m_clrArrow_Click; InvalidateRect(m_rcRTDN); OnClickRTDNBtn(); } else if (PtInRect(m_rcSlider, point)) { //鼠标左键点击滑块 m_clrSlider = m_clrSlider_Click; InvalidateRect(m_rcSlider); SetCapture(); m_bIsCaptrue = TRUE; } CBaseWnd::OnLButtonDown(nFlags, point); } void ScrollBar::OnLButtonUp(UINT nFlags, CPoint point) { // TODO: 在此添加消息处理程序代码和/或调用默认值 if (PtInRect(m_rcLTUP, point)) { //鼠标左键点击(左边/顶部)箭头 后 鼠标弹起 m_clrArrow = m_clrArrow_Hover; InvalidateRect(m_rcLTUP); } else if (PtInRect(m_rcRTDN, point)) { //鼠标左键点击(右边/底部)箭头 后 鼠标弹起 m_clrArrow = m_clrArrow_Hover; InvalidateRect(m_rcRTDN); } else if (PtInRect(m_rcSlider, point)) { //鼠标左键点击滑块 后 鼠标弹起 m_clrSlider = m_clrSlider_Hover; InvalidateRect(m_rcSlider); ReleaseCapture(); m_bIsCaptrue = FALSE; if (m_infoScroll.nTrackPos != m_infoScroll.nPos)//用nPos和nTrackPos比较是否滑块滑动过,nTrackPos在拖滑块中会更新 { switch (m_iBar) { case SB_HORZ: SendMessage(WM_HSCROLL, MAKEWPARAM(SB_THUMBPOSITION, m_rcSlider.left), NULL); break; case SB_VERT: SendMessage(WM_VSCROLL, MAKEWPARAM(SB_THUMBPOSITION, m_rcSlider.top), NULL); break; } } } if (m_bIsCaptrue) { ReleaseCapture(); m_bIsCaptrue = FALSE; if (m_infoScroll.nTrackPos != m_infoScroll.nPos)//用nPos和nTrackPos比较是否滑块滑动过,nTrackPos在拖滑块中会更新 { switch (m_iBar) { case SB_HORZ: SendMessage(WM_HSCROLL, MAKEWPARAM(SB_THUMBPOSITION, m_rcSlider.left), NULL); break; case SB_VERT: SendMessage(WM_VSCROLL, MAKEWPARAM(SB_THUMBPOSITION, m_rcSlider.top), NULL); break; } } } m_bIsEnd = FALSE; CBaseWnd::OnLButtonUp(nFlags, point); } void ScrollBar::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) { // TODO: 在此添加消息处理程序代码和/或调用默认值 if (pScrollBar == NULL)//NULL说明内部发送过来信息 { switch (nSBCode) { case SB_ENDSCROLL: { //结束滚动 //_output_debug_("水平滚动结束x:%d", nPos); if (m_pTargetWnd) { m_pTargetWnd->SendMessage(WM_HSCROLL, MAKEWPARAM(SB_ENDSCROLL, m_infoScroll.nPos), (LPARAM)this); } break; } case SB_THUMBTRACK: { //正在拖动滑块 m_infoScroll.nTrackPos = int((float)nPos / m_fRatio);//使用滑块的距离逆向比率得到目标的xPos if (m_pTargetWnd) { m_pTargetWnd->SendMessage(WM_HSCROLL, MAKEWPARAM(SB_THUMBTRACK, m_infoScroll.nTrackPos), (LPARAM)this); } break; } case SB_THUMBPOSITION: { //用户已拖动滚动框(拇指)并松开鼠标按钮 //_output_debug_("水平滚动条鼠标松开滑动,目标xPos:%d", m_infoScroll.nTrackPos); m_infoScroll.nPos = m_infoScroll.nTrackPos;//最终更新用户数据 SendMessage(WM_HSCROLL, MAKEWPARAM(SB_ENDSCROLL, m_rcSlider.left-m_iLTUPBtn), NULL); break; } case SB_LINELEFT: { //向左滚动一个单位 点击左箭头 //_output_debug_("水平滚动向左滚动一个单位:%d", nPos); m_fCorrectionLT += (float)nPos / m_fRatio;//计算目标控件的滚动距离 int pos = (int)m_fCorrectionLT; m_fCorrectionLT -= (float)pos; m_infoScroll.nPos -= pos; m_infoScroll.nPos = m_infoScroll.nPos < m_infoScroll.nMin ? m_infoScroll.nMin : m_infoScroll.nPos; m_infoScroll.nTrackPos = m_infoScroll.nPos; if (m_pTargetWnd) { m_pTargetWnd->SendMessage(WM_HSCROLL, MAKEWPARAM(SB_THUMBPOSITION, m_infoScroll.nPos), (LPARAM)this); } break; } case SB_LINERIGHT: { //向右滚动一个单位 点击右箭头 //_output_debug_("水平滚动向右滚动一个单位:%d", nPos); m_fCorrectionRD += (float)nPos / m_fRatio; int pos = (int)m_fCorrectionRD; m_fCorrectionRD -= (float)pos;//把小数位单独取出来留给后面的补正 m_infoScroll.nPos += pos;//使用滑块的距离逆向比率得到目标的xPos m_infoScroll.nPos = m_infoScroll.nPos > m_infoScroll.nMax ? m_infoScroll.nMax : m_infoScroll.nPos; m_infoScroll.nTrackPos = m_infoScroll.nPos; if (m_pTargetWnd) { m_pTargetWnd->SendMessage(WM_HSCROLL, MAKEWPARAM(SB_THUMBPOSITION, m_infoScroll.nPos), (LPARAM)this); } break; } case SB_LEFT: { //滚动到左边末尾 //_output_debug_("已经滚动到左边尽头."); //if (m_pTargetWnd) m_pTargetWnd->SendMessage(WM_HSCROLL, MAKEWPARAM(SB_LEFT, 0), (LPARAM)this); break; } case SB_RIGHT: { //滚动到右边末尾 //_output_debug_("已经滚动到右边尽头."); //if (m_pTargetWnd) m_pTargetWnd->SendMessage(WM_HSCROLL, MAKEWPARAM(SB_RIGHT, m_infoScroll.nMax), (LPARAM)this); break; } } } CBaseWnd::OnHScroll(nSBCode, nPos, pScrollBar); } void ScrollBar::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) { // TODO: 在此添加消息处理程序代码和/或调用默认值 if (pScrollBar == NULL)//NULL说明内部发送过来信息 { switch (nSBCode) { case SB_ENDSCROLL: { //结束滚动 //_output_debug_("垂直滚动结束y:%d", nPos); if (m_pTargetWnd) { m_pTargetWnd->SendMessage(WM_VSCROLL, MAKEWPARAM(SB_ENDSCROLL, m_infoScroll.nPos), (LPARAM)this); } break; } case SB_THUMBTRACK: { //正在拖动滑块 m_infoScroll.nTrackPos = int((float)nPos / m_fRatio);//使用滑块的距离逆向比率得到目标的xPos if (m_pTargetWnd) { m_pTargetWnd->SendMessage(WM_VSCROLL, MAKEWPARAM(SB_THUMBTRACK, m_infoScroll.nTrackPos), (LPARAM)this); } break; } case SB_THUMBPOSITION: { //用户已拖动滚动框(拇指)并松开鼠标按钮 //_output_debug_("垂直滚动条鼠标松开滑动,目标yPos: %d", m_infoScroll.nTrackPos); m_infoScroll.nPos = m_infoScroll.nTrackPos;//最终更新用户数据 SendMessage(WM_VSCROLL, MAKEWPARAM(SB_ENDSCROLL, m_rcSlider.top-m_iLTUPBtn), NULL); break; } case SB_LINEUP: { //向上滚动了一个单位 点击顶箭头 m_fCorrectionLT += int((float)nPos / m_fRatio);//使用滑块的距离逆向比率得到目标的xPos int pos = (int)m_fCorrectionLT; m_fCorrectionLT -= (float)pos; m_infoScroll.nPos -= pos; m_infoScroll.nPos = m_infoScroll.nPos < m_infoScroll.nMin ? m_infoScroll.nMin : m_infoScroll.nPos; m_infoScroll.nTrackPos = m_infoScroll.nPos; if (m_pTargetWnd) { m_pTargetWnd->SendMessage(WM_VSCROLL, MAKEWPARAM(SB_THUMBPOSITION, m_infoScroll.nPos), (LPARAM)this); } break; } case SB_LINEDOWN: { //向下滚动了一个单位 点击底箭头 m_fCorrectionRD += (float)nPos / m_fRatio; int pos = (int)m_fCorrectionRD; m_fCorrectionRD -= (float)pos;//把小数位单独取出来留给后面的补正 m_infoScroll.nPos += pos;//使用滑块的距离逆向比率得到目标的xPos m_infoScroll.nPos = m_infoScroll.nPos > m_infoScroll.nMax ? m_infoScroll.nMax : m_infoScroll.nPos; m_infoScroll.nTrackPos = m_infoScroll.nPos; if (m_pTargetWnd) { m_pTargetWnd->SendMessage(WM_VSCROLL, MAKEWPARAM(SB_THUMBPOSITION, m_infoScroll.nPos), (LPARAM)this); } break; } case SB_TOP: { //滚动到顶部 //_output_debug_("已经滚动到顶部尽头."); //if (m_pTargetWnd) m_pTargetWnd->SendMessage(WM_VSCROLL, MAKEWPARAM(SB_TOP, 0), (LPARAM)this); break; } case SB_BOTTOM: { //滚动到底部 //_output_debug_("已经滚动到底部尽头."); //if (m_pTargetWnd) m_pTargetWnd->SendMessage(WM_VSCROLL, MAKEWPARAM(SB_BOTTOM, 0), (LPARAM)this); break; } } } CBaseWnd::OnVScroll(nSBCode, nPos, pScrollBar); } void ScrollBar::OnDragSlider(const CPoint& _point) { CPoint point = {0, 0}; CRect rect = m_rcSlider; switch (m_iBar) { case SB_HORZ: { point.x = _point.x - m_ptMouseLastPoint.x; rect.OffsetRect(point); if (rect.left >= m_rcScroll.left && rect.right <= m_rcScroll.right) { //合法拖动滑块 m_rcSlider.left = rect.left;//更新滑块左边坐标 m_rcSlider.right = rect.right;//更新滑块右边坐标 InvalidateRect(m_rcScroll);//刷新通道 SendMessage(WM_HSCROLL, MAKEWPARAM(SB_THUMBTRACK, m_rcSlider.left-m_iLTUPBtn), NULL); m_bIsEnd = FALSE; } else { //拖动滑块不合法: 超出左边 或者 右边 if (!m_bIsEnd && rect.left < m_rcScroll.left) { //超出左边 m_bIsEnd = TRUE; SendMessage(WM_HSCROLL, MAKEWPARAM(SB_LEFT, m_rcScroll.left), NULL); } else if(!m_bIsEnd && rect.right > m_rcScroll.right) { //超出右边 m_bIsEnd = TRUE; SendMessage(WM_HSCROLL, MAKEWPARAM(SB_RIGHT, m_rcScroll.right), NULL); } } break; } case SB_VERT: { point.y = _point.y - m_ptMouseLastPoint.y; rect.OffsetRect(point); if (rect.top >= m_rcScroll.top && rect.bottom <= m_rcScroll.bottom) { //合法拖动滑块 m_rcSlider.top = rect.top;//更新滑块顶部坐标 m_rcSlider.bottom = rect.bottom;//更新滑块底部坐标 InvalidateRect(m_rcScroll);//刷新通道 SendMessage(WM_VSCROLL, MAKEWPARAM(SB_THUMBTRACK, m_rcSlider.top-m_iLTUPBtn), NULL); m_bIsEnd = FALSE; } else { //拖动滑块不合法: 超出顶部 或者 底部 if (!m_bIsEnd && rect.top < m_rcScroll.top) { //超出顶部 m_bIsEnd = TRUE; SendMessage(WM_VSCROLL, MAKEWPARAM(SB_TOP, m_rcScroll.top), NULL); } else if(!m_bIsEnd && rect.bottom > m_rcScroll.bottom) { //超出底部 m_bIsEnd = TRUE; SendMessage(WM_VSCROLL, MAKEWPARAM(SB_BOTTOM, m_rcScroll.bottom), NULL); } } break; } } } void ScrollBar::OnClickLTUPBtn()//点击了(左箭头/顶部箭头) { int iSpace = 0; int iPage = 0; switch (m_iBar) { case SB_HORZ: { //_output_debug_("点击了左箭头"); iSpace = m_rcScroll.Width() - m_rcSlider.Width();//计算出滑块能滑动的最大距离 iPage = int((float)iSpace / ((float)iSpace / 10.0f));//点击一次箭头 滑块移动的距离 if (m_rcSlider.left - iPage >= m_rcScroll.left) { //合法滑动 } else { //滑动可能超出左边 iPage = m_rcSlider.left-m_rcScroll.left;//重置到尽头 } if (iPage) { m_rcSlider.OffsetRect(-iPage, 0); InvalidateRect(m_rcScroll); SendMessage(WM_HSCROLL, MAKEWPARAM(SB_LINELEFT, iPage), NULL); } break; } case SB_VERT: { //_output_debug_("点击了顶部箭头"); iSpace = m_rcScroll.Height() - m_rcSlider.Height();//计算出滑块能滑动的最大距离 iPage = int((float)iSpace / ((float)iSpace / 10.0f));//点击一次箭头 滑块移动的距离 if (m_rcSlider.top - iPage >= m_rcScroll.top) { //合法滑动 } else { //滑动可能超出顶部 iPage = m_rcSlider.top - m_rcScroll.top;//重置到尽头 } if (iPage) { m_rcSlider.OffsetRect(0, -iPage); InvalidateRect(m_rcScroll); SendMessage(WM_VSCROLL, MAKEWPARAM(SB_LINEUP, iPage), NULL); } break; } } } void ScrollBar::OnClickRTDNBtn()//点击了(右箭头/底部箭头) { int iSpace = 0; int iPage = 0; switch (m_iBar) { case SB_HORZ: { //_output_debug_("点击了右箭头"); iSpace = m_rcScroll.Width() - m_rcSlider.Width();//计算出滑块能滑动的最大距离 iPage = int((float)iSpace / ((float)iSpace / 10.0f));//点击一次箭头 滑块移动的距离 if (m_rcSlider.right + iPage <= m_rcScroll.right) { //合法滑动 } else { //滑动可能超出右边 iPage = m_rcScroll.right - m_rcSlider.right;//重置到尽头 } if (iPage) { m_rcSlider.OffsetRect(iPage, 0); InvalidateRect(m_rcScroll); SendMessage(WM_HSCROLL, MAKEWPARAM(SB_LINERIGHT, iPage), NULL); } break; } case SB_VERT: { //_output_debug_("点击了底部箭头"); iSpace = m_rcScroll.Height() - m_rcSlider.Height();//计算出滑块能滑动的最大距离 iPage = int((float)iSpace / ((float)iSpace / 10.0f));//点击一次箭头 滑块移动的距离 if (m_rcSlider.bottom + iPage <= m_rcScroll.bottom) { //合法滑动 } else { //滑动可能超出底部 iPage = m_rcScroll.bottom - m_rcSlider.bottom;//重置到尽头 } if (iPage) { m_rcSlider.OffsetRect(0, iPage); InvalidateRect(m_rcScroll); SendMessage(WM_VSCROLL, MAKEWPARAM(SB_LINEDOWN, iPage), NULL); } break; } } } void ScrollBar::SetTarget(CWnd* _pTargetWnd) { m_pTargetWnd = _pTargetWnd; } BOOL ScrollBar::SetScrollInfo(SCROLLINFO& _refScrollInfo, BOOL _bRedraw) { if (_refScrollInfo.nMax > (int)_refScrollInfo.nPage) { CRect rect = m_infoScrollBar.rcScrollBar;//取出滚动条的范围 float fRatio = 0.0f;//比率 int iSliderLen = 0;//滑块(长度/宽度) int iPos = 0; int iLTUP = 0; int iRTDN = 0; bool bIsValid = false; if ((_refScrollInfo.fMask & (SIF_RANGE | SIF_PAGE | SIF_POS)) == false)//提供的fMask权限不足 { return false; } switch (m_iBar) { case SB_HORZ: { fRatio = (float)(rect.Width() - (m_iLTUPBtn + m_iRTDNBtn)) / (float)_refScrollInfo.nMax;//计算比率: (总长度-2个箭头) / 目标控件内容最大可视范围 iSliderLen = (int)((float)rect.Width() * fRatio);//计算滑块的(长度) 水平滚动条 if (iSliderLen < m_iMinSlider)//如果滑块太短了 { iSliderLen = m_iMinSlider;//使用最小滑块长度 fRatio = (float)(rect.Width() - (m_iLTUPBtn + m_iRTDNBtn + m_iMinSlider)) / (float)_refScrollInfo.nMax;//重新计算比率: (总长度-2个箭头-最小滑块长度) / 目标控件内容最大可视范围 } iPos = (int)((float)_refScrollInfo.nPos * fRatio);//根据提供的nPos算出应该滚动的距离 iLTUP = iPos + m_iLTUPBtn;//算出滑块左边的坐标值 iRTDN = iLTUP + iSliderLen;//算出滑块右边的坐标值 if (iLTUP >= m_rcScroll.left && iRTDN <= m_rcScroll.right)//如果滑块左右两边都位于滚动条通道内,提供的nPos合法 { m_rcSlider.left = iLTUP; m_rcSlider.right = iRTDN; if (_bRedraw) InvalidateRect(m_rcScroll);//更新通道内容 bIsValid = true;//操作合法 m_fRatio = fRatio;//更新比率 } else { //提供的nPos不合法 return FALSE; } break; } case SB_VERT: { fRatio = (float)(rect.Height() - (m_iLTUPBtn + m_iRTDNBtn)) / (float)_refScrollInfo.nMax;//计算比率: (总宽度-2个箭头) / 目标控件内容最大可视范围 iSliderLen = (int)((float)rect.Height() * fRatio);//计算滑块的(宽度) 垂直滚动条 if (iSliderLen < m_iMinSlider)//如果滑块太短了 { iSliderLen = m_iMinSlider;//使用最小滑块宽度 fRatio = (float)(rect.Height() - (m_iLTUPBtn + m_iRTDNBtn + m_iMinSlider)) / (float)_refScrollInfo.nMax;//重新计算比率: (总宽度-2个箭头-最小滑块宽度) / 目标控件内容最大可视范围 } iPos = (int)((float)_refScrollInfo.nPos * fRatio);//根据提供的nPos算出应该滚动的距离 iLTUP = iPos + m_iLTUPBtn;//算出滑块顶部的坐标值 iRTDN = iLTUP + iSliderLen;//算出滑块底部的坐标值 if (iLTUP >= m_rcScroll.top && iRTDN <= m_rcScroll.bottom)//如果滑块上下两边都位于滚动条通道内,提供的nPos合法 { m_rcSlider.top = iLTUP; m_rcSlider.bottom = iRTDN; if (_bRedraw) InvalidateRect(m_rcScroll);//更新通道内容 bIsValid = true;//操作合法 m_fRatio = fRatio;//更新比率 } else { //提供的nPos不合法 return FALSE; } break; } } //更新scroll info 数据 if (bIsValid && _refScrollInfo.fMask & SIF_ALL) { m_infoScroll = _refScrollInfo;//全部数据复制给内部info m_infoScroll.cbSize = sizeof SCROLLINFO;//系统性修正数据-避免提供的数据有问题 m_infoScroll.fMask = SIF_ALL;//系统性修正数据-避免提供的数据有问题 return TRUE; } else if (bIsValid) { if (_refScrollInfo.fMask & SIF_RANGE) { m_infoScroll.nMin = _refScrollInfo.nMin; m_infoScroll.nMax = _refScrollInfo.nMax; } if (_refScrollInfo.fMask & SIF_PAGE) { m_infoScroll.nPage = _refScrollInfo.nPage; } if (_refScrollInfo.fMask & SIF_POS) { m_infoScroll.nPos = _refScrollInfo.nPos; } //SIF_DISABLENOSCROLL //不处理 //SIF_TRACKPOS //系统内部处理 return TRUE; } } return FALSE; } BOOL ScrollBar::SetScrollPos(int _iPos, BOOL _bRedraw) { int iPos = (int)roundf((float)_iPos * m_fRatio);//根据提供的nPos算出应该滚动的距离 CRect rect; if (_iPos > -1) { switch (m_iBar) { case SB_HORZ: { iPos += m_iLTUPBtn; rect = m_rcSlider; rect.OffsetRect(iPos, 0); if (rect.right <= m_rcScroll.right) { m_rcSlider = rect; if(_bRedraw)InvalidateRect(m_rcScroll); m_infoScroll.nPos = _iPos; m_infoScroll.nTrackPos = _iPos; return TRUE; } else { m_rcSlider.right = m_rcScroll.right; m_rcSlider.left = m_rcSlider.right - rect.Width(); if (_bRedraw)InvalidateRect(m_rcScroll); m_infoScroll.nPos = _iPos; m_infoScroll.nTrackPos = _iPos; } break; } case SB_VERT: { iPos += m_iLTUPBtn; rect = m_rcSlider; rect.OffsetRect(0, iPos); if (rect.bottom <= m_rcScroll.bottom) { m_rcSlider = rect; if (_bRedraw)InvalidateRect(m_rcScroll); m_infoScroll.nPos = _iPos; m_infoScroll.nTrackPos = _iPos; return TRUE; } else { m_rcSlider.bottom = m_rcScroll.bottom; m_rcSlider.top = m_rcScroll.bottom - rect.Height(); if (_bRedraw)InvalidateRect(m_rcScroll); m_infoScroll.nPos = _iPos; m_infoScroll.nTrackPos = _iPos; } break; } } } return FALSE; }
07-02
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值