4、1 字元輸出
4-1 程式
迴圈輸出介面介面
// 4-1_文字輸出.cpp : 定義應用程式的入口點。 // #include "pch.h" #include "framework.h" #include "4-1_文字輸出.h" #define MAX_LOADSTRING 100 #define LINEHEIGHT 15 // 全域性變數: HINSTANCE hInst; // 當前例項 WCHAR szTitle[MAX_LOADSTRING]; // 標題欄文字 WCHAR szWindowClass[MAX_LOADSTRING]; // 主視窗類名 // 此程式碼模組中包含的函式的前向宣告: ATOM MyRegisterClass(HINSTANCE hInstance); BOOL InitInstance(HINSTANCE, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM); int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) { UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine); // TODO: 在此處放置程式碼。 // 初始化全域性字串 LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); LoadStringW(hInstance, IDC_MY41, szWindowClass, MAX_LOADSTRING); MyRegisterClass(hInstance); // 執行應用程式初始化: if (!InitInstance (hInstance, nCmdShow)) { return FALSE; } HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_MY41)); MSG msg; // 主訊息迴圈: while (GetMessage(&msg, nullptr, 0, 0)) { if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return (int) msg.wParam; } // // 函式: MyRegisterClass() // // 目標: 註冊視窗類。 // ATOM MyRegisterClass(HINSTANCE hInstance) { WNDCLASSEXW wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MY41)); wcex.hCursor = LoadCursor(nullptr, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = NULL; // MAKEINTRESOURCEW(IDC_MY41); wcex.lpszClassName = szWindowClass; wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); return RegisterClassExW(&wcex); } // // 函式: InitInstance(HINSTANCE, int) // // 目標: 儲存例項控制程式碼並建立主視窗 // // 註釋: // // 在此函式中,我們在全域性變數中儲存例項控制程式碼並 // 建立和顯示主程式視窗。 // BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { hInst = hInstance; // 將例項控制程式碼儲存在全域性變數中 HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr); if (!hWnd) { return FALSE; } ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; } // // 函式: WndProc(HWND, UINT, WPARAM, LPARAM) // // 目標: 處理主視窗的訊息。 // // WM_COMMAND - 處理應用程式選單 // WM_PAINT - 繪製主視窗 // WM_DESTROY - 傳送退出訊息並返回 // // LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_COMMAND: { int wmId = LOWORD(wParam); // 分析選單選擇: switch (wmId) { case IDM_ABOUT: DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); break; case IDM_EXIT: DestroyWindow(hWnd); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } } break; case WM_PAINT: { TCHAR szBuffer[1024]; PAINTSTRUCT ps; HDC hdc = BeginPaint(hWnd, &ps); // TODO: 在此處新增使用 hdc 的任何繪圖程式碼... for (int i = 0; i < 100; ++i) { _sntprintf(szBuffer, 1024, TEXT("文字輸出 %d"), i+1); TextOut(hdc, 0, i*LINEHEIGHT, szBuffer, lstrlen(szBuffer)); } EndPaint(hWnd, &ps); } break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } // “關於”框的訊息處理程式。 INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { UNREFERENCED_PARAMETER(lParam); switch (message) { case WM_INITDIALOG: return (INT_PTR)TRUE; case WM_COMMAND: if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) { EndDialog(hDlg, LOWORD(wParam)); return (INT_PTR)TRUE; } break; } return (INT_PTR)FALSE; }
4、2 系統字型
4-2 程式
動態計算字型
// 4-2_動態計算字型.cpp : 定義應用程式的入口點。 // #include "pch.h" #include "framework.h" #include "4-2_動態計算字型.h" #define MAX_LOADSTRING 100 // 全域性變數: HINSTANCE hInst; // 當前例項 WCHAR szTitle[MAX_LOADSTRING]; // 標題欄文字 WCHAR szWindowClass[MAX_LOADSTRING]; // 主視窗類名 // 此程式碼模組中包含的函式的前向宣告: ATOM MyRegisterClass(HINSTANCE hInstance); BOOL InitInstance(HINSTANCE, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM); int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) { UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine); // TODO: 在此處放置程式碼。 // 初始化全域性字串 LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); LoadStringW(hInstance, IDC_MY42, szWindowClass, MAX_LOADSTRING); MyRegisterClass(hInstance); // 執行應用程式初始化: if (!InitInstance (hInstance, nCmdShow)) { return FALSE; } HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_MY42)); MSG msg; // 主訊息迴圈: while (GetMessage(&msg, nullptr, 0, 0)) { if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return (int) msg.wParam; } // // 函式: MyRegisterClass() // // 目標: 註冊視窗類。 // ATOM MyRegisterClass(HINSTANCE hInstance) { WNDCLASSEXW wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MY42)); wcex.hCursor = LoadCursor(nullptr, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = NULL;//MAKEINTRESOURCEW(IDC_MY42); wcex.lpszClassName = szWindowClass; wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); return RegisterClassExW(&wcex); } // // 函式: InitInstance(HINSTANCE, int) // // 目標: 儲存例項控制程式碼並建立主視窗 // // 註釋: // // 在此函式中,我們在全域性變數中儲存例項控制程式碼並 // 建立和顯示主程式視窗。 // BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { hInst = hInstance; // 將例項控制程式碼儲存在全域性變數中 HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr); if (!hWnd) { return FALSE; } ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; } // // 函式: WndProc(HWND, UINT, WPARAM, LPARAM) // // 目標: 處理主視窗的訊息。 // // WM_COMMAND - 處理應用程式選單 // WM_PAINT - 繪製主視窗 // WM_DESTROY - 傳送退出訊息並返回 // // LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { static int cyChar; //字元高度,行高,行間距 static int cxChar;//字元寬度 static int cxCaps; //大寫字元 static int cxScreen, cyScreen; //螢幕的寬高 TCHAR szBuffer[40]; int iLength; TEXTMETRIC tm; PAINTSTRUCT ps; HDC hdc; case WM_CREATE: hdc = GetDC(hWnd); GetTextMetrics(hdc, &tm); //小寫字元的寬度 cxChar = tm.tmAveCharWidth; //小寫字元的高度 + 行間距 cyChar = tm.tmHeight + tm.tmExternalLeading; //大寫字元一般設為小寫字元的1.5倍 或 等寬的字元就和小寫相等 //檢查 低位是 1非等寬字型 0 等寬字型 cxCaps = ((tm.tmPitchAndFamily & 1) ? 3 : 2) * cxChar / 2; //獲取螢幕的寬度 cxScreen = GetSystemMetrics(SM_CXSCREEN); //獲取螢幕的高度 cyScreen = GetSystemMetrics(SM_CYSCREEN); ReleaseDC(hWnd, hdc); break; case WM_COMMAND: { int wmId = LOWORD(wParam); // 分析選單選擇: switch (wmId) { case IDM_ABOUT: DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); break; case IDM_EXIT: DestroyWindow(hWnd); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } } break; case WM_PAINT: { hdc = BeginPaint(hWnd, &ps); // TODO: 在此處新增使用 hdc 的任何繪圖程式碼... //顯示螢幕寬度 TextOut(hdc, 0, 0, TEXT("SM_CXSCREEN"), lstrlen(TEXT("SM_CXSCREEN"))); //寬度describe TextOut(hdc, 22*cxCaps, 0, TEXT("Screen width in pixels"), lstrlen(TEXT("Screen width in pixels"))); //對齊方式 SetTextAlign(hdc,TA_RIGHT | TA_TOP); iLength = _sntprintf(szBuffer, 40, TEXT("%d"), cxScreen); TextOut(hdc, 22 * cxCaps + 40 * cxChar, 0, szBuffer, iLength); //對齊方式 SetTextAlign(hdc, TA_LEFT | TA_TOP); //顯示螢幕高度 TextOut(hdc, 0, cyChar, TEXT("SM_CYSCREEN"), lstrlen(TEXT("SM_CYSCREEN"))); //高度describe TextOut(hdc, 22 * cxCaps, cyChar, TEXT("Screen height in pixels"), lstrlen(TEXT("Screen height in pixels"))); //對齊方式 SetTextAlign(hdc, TA_RIGHT | TA_TOP); iLength = _sntprintf(szBuffer, 40, TEXT("%d"), cyScreen); TextOut(hdc, 22 * cxCaps + 40 * cxChar, cyChar, szBuffer, iLength); //對齊方式 SetTextAlign(hdc, TA_LEFT | TA_TOP); EndPaint(hWnd, &ps); } break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } // “關於”框的訊息處理程式。 INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { UNREFERENCED_PARAMETER(lParam); switch (message) { case WM_INITDIALOG: return (INT_PTR)TRUE; case WM_COMMAND: if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) { EndDialog(hDlg, LOWORD(wParam)); return (INT_PTR)TRUE; } break; } return (INT_PTR)FALSE; }
4、3 滾動條
4-3 程式
滾動條。(下面自動建立的程式碼中不需要的程式碼已刪)
// 4-3_滾動條.cpp : 定義應用程式的入口點。 // #include "pch.h" #include "framework.h" #include "4-3_滾動條.h" #define MAX_LOADSTRING 100 #define MAX_LINE 200 // 全域性變數: HINSTANCE hInst; // 當前例項 WCHAR szTitle[MAX_LOADSTRING]; // 標題欄文字 WCHAR szWindowClass[MAX_LOADSTRING]; // 主視窗類名 // 此程式碼模組中包含的函式的前向宣告: ATOM MyRegisterClass(HINSTANCE hInstance); BOOL InitInstance(HINSTANCE, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) { UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine); // TODO: 在此處放置程式碼。 // 初始化全域性字串 LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); LoadStringW(hInstance, IDC_MY43, szWindowClass, MAX_LOADSTRING); MyRegisterClass(hInstance); // 執行應用程式初始化: if (!InitInstance (hInstance, nCmdShow)) { return FALSE; } HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_MY43)); MSG msg; // 主訊息迴圈: while (GetMessage(&msg, nullptr, 0, 0)) { if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return (int) msg.wParam; } // // 函式: MyRegisterClass() // // 目標: 註冊視窗類。 // ATOM MyRegisterClass(HINSTANCE hInstance) { WNDCLASSEXW wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MY43)); wcex.hCursor = LoadCursor(nullptr, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = NULL;// MAKEINTRESOURCEW(IDC_MY43); wcex.lpszClassName = szWindowClass; wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); return RegisterClassExW(&wcex); } // // 函式: InitInstance(HINSTANCE, int) // // 目標: 儲存例項控制程式碼並建立主視窗 // // 註釋: // // 在此函式中,我們在全域性變數中儲存例項控制程式碼並 // 建立和顯示主程式視窗。 // BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { hInst = hInstance; // 將例項控制程式碼儲存在全域性變數中 HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW | WS_VSCROLL, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr); if (!hWnd) { return FALSE; } ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; } // // 函式: WndProc(HWND, UINT, WPARAM, LPARAM) // // 目標: 處理主視窗的訊息。 // // WM_COMMAND - 處理應用程式選單 // WM_PAINT - 繪製主視窗 // WM_DESTROY - 傳送退出訊息並返回 // // LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { PAINTSTRUCT ps; HDC hdc; static int cyChar; //字型高度 int x, y; //文字顯示座標 static int iVscrollPos; //滾動條位置 static int cyClient; //客戶區 TEXTMETRIC tm; SCROLLINFO si; case WM_SIZE: cyClient = HIWORD(lParam); //調整視窗大小,引數中可獲取高度 si.cbSize = sizeof(si); si.fMask = SIF_RANGE | SIF_PAGE ; si.nMin = 0; si.nMax = MAX_LINE - 1; si.nPage = cyClient / cyChar; SetScrollInfo(hWnd,SB_VERT,&si,TRUE); break; case WM_CREATE: hdc = GetDC(hWnd); GetTextMetrics(hdc,&tm); //文字度量 cyChar = tm.tmHeight + tm.tmExternalLeading; //文字高度 + 行間距 ReleaseDC(hWnd,hdc); iVscrollPos = 0; //滾動條的初始值 SetScrollRange(hWnd,SB_VERT,0,MAX_LINE-1,FALSE); //設定滾動條範圍 SetScrollPos(hWnd,SB_VERT,iVscrollPos,TRUE); //設定位置 return 0; case WM_PAINT: { hdc = BeginPaint(hWnd, &ps); // TODO: 在此處新增使用 hdc 的任何繪圖程式碼... TCHAR szBuffer[1024]; //字元緩衝區 for (int i = 0; i < MAX_LINE; i++) { x = 0; //水平垂直座標 y =cyChar *(i - iVscrollPos); //垂直繪製座標 _snwprintf(szBuffer, 1024, TEXT("滾動條 %d"), i+1); //格式轉化 TextOut(hdc, x, y, szBuffer, lstrlen(szBuffer)); //文字輸出 } EndPaint(hWnd, &ps); } break; case WM_VSCROLL: switch (LOWORD(wParam)) { case SB_LINEUP: //按鈕上 iVscrollPos -= 1; break; case SB_LINEDOWN: //按鈕下 iVscrollPos+= 1; break; case SB_PAGEDOWN: iVscrollPos += cyClient / cyChar; //點選下一頁 break; case SB_PAGEUP: iVscrollPos -= cyClient / cyChar; //點選上一頁 break; case SB_THUMBPOSITION: //拖動滑鼠 iVscrollPos = HIWORD(wParam); //移動是獲取位置 default: break; } iVscrollPos = max(0, min(iVscrollPos, MAX_LINE - 1)); //設定範圍 if (iVscrollPos != GetScrollPos(hWnd, SB_VERT)) //當前位置和實際位置比較 { SetScrollPos(hWnd, SB_VERT, iVscrollPos, TRUE); //重新設定位置 InvalidateRect(hWnd,NULL,TRUE); //重新繪製視窗 } break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; }
5、例子
用上面你的函式做一個例子。
// 4_4_例子Sysmets.cpp : 定義應用程式的入口點。 // #include "pch.h" #include "framework.h" #include "4_4_例子Sysmets.h" #include "data.h" #define MAX_LOADSTRING 100 // 全域性變數: HINSTANCE hInst; // 當前例項 WCHAR szTitle[MAX_LOADSTRING]; // 標題欄文字 WCHAR szWindowClass[MAX_LOADSTRING]; // 主視窗類名 // 此程式碼模組中包含的函式的前向宣告: ATOM MyRegisterClass(HINSTANCE hInstance); BOOL InitInstance(HINSTANCE, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM); int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) { UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine); // TODO: 在此處放置程式碼。 // 初始化全域性字串 LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); LoadStringW(hInstance, IDC_MY44SYSMETS, szWindowClass, MAX_LOADSTRING); MyRegisterClass(hInstance); // 執行應用程式初始化: if (!InitInstance (hInstance, nCmdShow)) { return FALSE; } HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_MY44SYSMETS)); MSG msg; // 主訊息迴圈: while (GetMessage(&msg, nullptr, 0, 0)) { if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return (int) msg.wParam; } // // 函式: MyRegisterClass() // // 目標: 註冊視窗類。 // ATOM MyRegisterClass(HINSTANCE hInstance) { WNDCLASSEXW wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MY44SYSMETS)); wcex.hCursor = LoadCursor(nullptr, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = NULL;//MAKEINTRESOURCEW(IDC_MY44SYSMETS); wcex.lpszClassName = szWindowClass; wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); return RegisterClassExW(&wcex); } // // 函式: InitInstance(HINSTANCE, int) // // 目標: 儲存例項控制程式碼並建立主視窗 // // 註釋: // // 在此函式中,我們在全域性變數中儲存例項控制程式碼並 // 建立和顯示主程式視窗。 // BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { hInst = hInstance; // 將例項控制程式碼儲存在全域性變數中 HWND hWnd = CreateWindowW(szWindowClass, TEXT("Get System Metrics NO.1"), WS_OVERLAPPEDWINDOW | WS_VSCROLL, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr); if (!hWnd) { return FALSE; } ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; } // // 函式: WndProc(HWND, UINT, WPARAM, LPARAM) // // 目標: 處理主視窗的訊息。 // // WM_COMMAND - 處理應用程式選單 // WM_PAINT - 繪製主視窗 // WM_DESTROY - 傳送退出訊息並返回 // // LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { static int cxChar, cxCaps, cyChar, iVScrollPos,cyClient; PAINTSTRUCT ps; HDC hdc; TCHAR szBuffer[10]; TEXTMETRIC tm; size_t y; SCROLLINFO si; size_t iVertPos; size_t iPaintBeg, iPaintEnd; case WM_CREATE: { hdc = GetDC(hWnd); GetTextMetrics(hdc,&tm); cxChar = tm.tmAveCharWidth; //變寬的字型是小寫字型的1.5倍 cxCaps = (tm.tmPitchAndFamily & 1 ? 3 : 2) * cxChar / 2; //字型的高度 + 外部的間距(字型設計的人推薦的加) cyChar = tm.tmHeight + tm.tmExternalLeading; ReleaseDC(hWnd, hdc); iVScrollPos = 0; //SetScrollRange(hWnd, SB_VERT, 0, NUMLINES - 1, FALSE); //SetScrollPos(hWnd, SB_VERT, iVScrollPos, TRUE); return 0; } case WM_SIZE: //客戶區的高度 cyClient = HIWORD(lParam); si.cbSize = sizeof(si); si.fMask = SIF_RANGE | SIF_PAGE; //客戶區一頁有多少行 si.nPage = cyClient / cyChar; si.nMin = 0; si.nMax = NUMLINES; SetScrollInfo(hWnd, SB_VERT, &si, true); break; case WM_COMMAND: { int wmId = LOWORD(wParam); // 分析選單選擇: switch (wmId) { case IDM_ABOUT: DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); break; case IDM_EXIT: DestroyWindow(hWnd); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } } break; case WM_PAINT: { hdc = BeginPaint(hWnd, &ps); // TODO: 在此處新增使用 hdc 的任何繪圖程式碼... si.cbSize = sizeof(si); si.fMask = SIF_POS; GetScrollInfo(hWnd, SB_VERT, &si); iVertPos = si.nPos; //無效區域開始位置 iPaintBeg = max(0, iVertPos + ps.rcPaint.top/cyChar); //無效區域結束位置 iPaintEnd = min(NUMLINES - 1, iVertPos + ps.rcPaint.bottom / cyChar); for (int i = iPaintBeg; i <= iPaintEnd; ++i) { y = cyChar * (i - iVertPos); TextOut(hdc, 0, y, sysmetrics[i].szLabel, lstrlen(sysmetrics[i].szLabel)); TextOut(hdc, 22 * cxCaps, y, sysmetrics[i].szDesc, lstrlen(sysmetrics[i].szDesc)); SetTextAlign(hdc, TA_RIGHT | TA_TOP); TextOut(hdc, 22 * cxCaps + 40 * cxChar, y, szBuffer, wsprintf(szBuffer, TEXT("%5d"), GetSystemMetrics(sysmetrics[i].iIndex))); SetTextAlign(hdc, TA_LEFT | TA_TOP); } EndPaint(hWnd, &ps); } break; case WM_VSCROLL: si.cbSize = sizeof(si); si.fMask = SIF_ALL; GetScrollInfo(hWnd,SB_VERT,&si); iVertPos = si.nPos; switch (LOWORD(wParam)) { case SB_LINEUP: //iVScrollPos -= 1; si.nPos -= 1; break; case SB_LINEDOWN: //iVScrollPos += 1; si.nPos += 1; break; case SB_PAGEUP: //iVScrollPos -= cyClient / cyChar; si.nPos -= si.nPage; break; case SB_PAGEDOWN: //iVScrollPos += cyClient / cyChar; si.nPos += si.nPage; break; //case SB_THUMBPOSITION: case SB_THUMBTRACK: //iVScrollPos = HIWORD(wParam); si.nPos = si.nTrackPos; break; default: break; } si.fMask = SIF_POS; SetScrollInfo(hWnd, SB_VERT, &si, TRUE); GetScrollInfo(hWnd, SB_VERT, &si); if (si.nPos != iVertPos) { //重新整理滾動視窗客戶區的內容 ScrollWindow(hWnd, 0, cyChar*(iVertPos - si.nPos), NULL, NULL); UpdateWindow(hWnd); } //iVScrollPos = max(0, min(iVScrollPos, NUMLINES - 1)); //if (iVScrollPos != GetScrollPos(hWnd,SB_VERT)) //{ // SetScrollPos(hWnd, SB_VERT, iVScrollPos, true); // InvalidateRect(hWnd, NULL, TRUE); // UpdateWindow(hWnd); //} break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } // “關於”框的訊息處理程式。 INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { UNREFERENCED_PARAMETER(lParam); switch (message) { case WM_INITDIALOG: return (INT_PTR)TRUE; case WM_COMMAND: if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) { EndDialog(hDlg, LOWORD(wParam)); return (INT_PTR)TRUE; } break; } return (INT_PTR)FALSE; }
#pragma once //data.h 標頭檔案內容 #define NUMLINES ((int) (sizeof sysmetrics / sizeof sysmetrics [0])) struct { int iIndex; TCHAR * szLabel; TCHAR * szDesc; } sysmetrics[] = { SM_CXSCREEN, TEXT("SM_CXSCREEN"), TEXT("Screen width in pixels"), SM_CYSCREEN, TEXT("SM_CYSCREEN"), TEXT("Screen height in pixels"), SM_CXVSCROLL, TEXT("SM_CXVSCROLL"), TEXT("Vertical scroll width"), SM_CYHSCROLL, TEXT("SM_CYHSCROLL"), TEXT("Horizontal scroll height"), SM_CYCAPTION, TEXT("SM_CYCAPTION"), TEXT("Caption bar height"), SM_CXBORDER, TEXT("SM_CXBORDER"), TEXT("Window border width"), SM_CYBORDER, TEXT("SM_CYBORDER"), TEXT("Window border height"), SM_CXFIXEDFRAME, TEXT("SM_CXFIXEDFRAME"), TEXT("Dialog window frame width"), SM_CYFIXEDFRAME, TEXT("SM_CYFIXEDFRAME"), TEXT("Dialog window frame height"), SM_CYVTHUMB, TEXT("SM_CYVTHUMB"), TEXT("Vertical scroll thumb height"), SM_CXHTHUMB, TEXT("SM_CXHTHUMB"), TEXT("Horizontal scroll thumb width"), SM_CXICON, TEXT("SM_CXICON"), TEXT("Icon width"), SM_CYICON, TEXT("SM_CYICON"), TEXT("Icon height"), SM_CXCURSOR, TEXT("SM_CXCURSOR"), TEXT("Cursor width"), SM_CYCURSOR, TEXT("SM_CYCURSOR"), TEXT("Cursor height"), SM_CYMENU, TEXT("SM_CYMENU"), TEXT("Menu bar height"), SM_CXFULLSCREEN, TEXT("SM_CXFULLSCREEN"), TEXT("Full screen client area width"), SM_CYFULLSCREEN, TEXT("SM_CYFULLSCREEN"), TEXT("Full screen client area height"), SM_CYKANJIWINDOW, TEXT("SM_CYKANJIWINDOW"), TEXT("Kanji window height"), SM_MOUSEPRESENT, TEXT("SM_MOUSEPRESENT"), TEXT("Mouse present flag"), SM_CYVSCROLL, TEXT("SM_CYVSCROLL"), TEXT("Vertical scroll arrow height"), SM_CXHSCROLL, TEXT("SM_CXHSCROLL"), TEXT("Horizontal scroll arrow width"), SM_DEBUG, TEXT("SM_DEBUG"), TEXT("Debug version flag"), SM_SWAPBUTTON, TEXT("SM_SWAPBUTTON"), TEXT("Mouse buttons swapped flag"), SM_CXMIN, TEXT("SM_CXMIN"), TEXT("Minimum window width"), SM_CYMIN, TEXT("SM_CYMIN"), TEXT("Minimum window height"), SM_CXSIZE, TEXT("SM_CXSIZE"), TEXT("Min/Max/Close button width"), SM_CYSIZE, TEXT("SM_CYSIZE"), TEXT("Min/Max/Close button height"), SM_CXSIZEFRAME, TEXT("SM_CXSIZEFRAME"), TEXT("Window sizing frame width"), SM_CYSIZEFRAME, TEXT("SM_CYSIZEFRAME"), TEXT("Window sizing frame height"), SM_CXMINTRACK, TEXT("SM_CXMINTRACK"), TEXT("Minimum window tracking width"), SM_CYMINTRACK, TEXT("SM_CYMINTRACK"), TEXT("Minimum window tracking height"), SM_CXDOUBLECLK, TEXT("SM_CXDOUBLECLK"), TEXT("Double click x tolerance"), SM_CYDOUBLECLK, TEXT("SM_CYDOUBLECLK"), TEXT("Double click y tolerance"), SM_CXICONSPACING, TEXT("SM_CXICONSPACING"), TEXT("Horizontal icon spacing"), SM_CYICONSPACING, TEXT("SM_CYICONSPACING"), TEXT("Vertical icon spacing"), SM_MENUDROPALIGNMENT, TEXT("SM_MENUDROPALIGNMENT"), TEXT("Left or right menu drop"), SM_PENWINDOWS, TEXT("SM_PENWINDOWS"), TEXT("Pen extensions installed"), SM_DBCSENABLED, TEXT("SM_DBCSENABLED"), TEXT("Double-Byte Char Set enabled"), SM_CMOUSEBUTTONS, TEXT("SM_CMOUSEBUTTONS"), TEXT("Number of mouse buttons"), SM_SECURE, TEXT("SM_SECURE"), TEXT("Security present flag"), SM_CXEDGE, TEXT("SM_CXEDGE"), TEXT("3-D border width"), SM_CYEDGE, TEXT("SM_CYEDGE"), TEXT("3-D border height"), SM_CXMINSPACING, TEXT("SM_CXMINSPACING"), TEXT("Minimized window spacing width"), SM_CYMINSPACING, TEXT("SM_CYMINSPACING"), TEXT("Minimized window spacing height"), SM_CXSMICON, TEXT("SM_CXSMICON"), TEXT("Small icon width"), SM_CYSMICON, TEXT("SM_CYSMICON"), TEXT("Small icon height"), SM_CYSMCAPTION, TEXT("SM_CYSMCAPTION"), TEXT("Small caption height"), SM_CXSMSIZE, TEXT("SM_CXSMSIZE"), TEXT("Small caption button width"), SM_CYSMSIZE, TEXT("SM_CYSMSIZE"), TEXT("Small caption button height"), SM_CXMENUSIZE, TEXT("SM_CXMENUSIZE"), TEXT("Menu bar button width"), SM_CYMENUSIZE, TEXT("SM_CYMENUSIZE"), TEXT("Menu bar button height"), SM_ARRANGE, TEXT("SM_ARRANGE"), TEXT("How minimized windows arranged"), SM_CXMINIMIZED, TEXT("SM_CXMINIMIZED"), TEXT("Minimized window width"), SM_CYMINIMIZED, TEXT("SM_CYMINIMIZED"), TEXT("Minimized window height"), SM_CXMAXTRACK, TEXT("SM_CXMAXTRACK"), TEXT("Maximum draggable width"), SM_CYMAXTRACK, TEXT("SM_CYMAXTRACK"), TEXT("Maximum draggable height"), SM_CXMAXIMIZED, TEXT("SM_CXMAXIMIZED"), TEXT("Width of maximized window"), SM_CYMAXIMIZED, TEXT("SM_CYMAXIMIZED"), TEXT("Height of maximized window"), SM_NETWORK, TEXT("SM_NETWORK"), TEXT("Network present flag"), SM_CLEANBOOT, TEXT("SM_CLEANBOOT"), TEXT("How system was booted"), SM_CXDRAG, TEXT("SM_CXDRAG"), TEXT("Avoid drag x tolerance"), SM_CYDRAG, TEXT("SM_CYDRAG"), TEXT("Avoid drag y tolerance"), SM_SHOWSOUNDS, TEXT("SM_SHOWSOUNDS"), TEXT("Present sounds visually"), SM_CXMENUCHECK, TEXT("SM_CXMENUCHECK"), TEXT("Menu check-mark width"), SM_CYMENUCHECK, TEXT("SM_CYMENUCHECK"), TEXT("Menu check-mark height"), SM_SLOWMACHINE, TEXT("SM_SLOWMACHINE"), TEXT("Slow processor flag"), SM_MIDEASTENABLED, TEXT("SM_MIDEASTENABLED"), TEXT("Hebrew and Arabic enabled flag"), SM_MOUSEWHEELPRESENT, TEXT("SM_MOUSEWHEELPRESENT"), TEXT("Mouse wheel present flag"), SM_XVIRTUALSCREEN, TEXT("SM_XVIRTUALSCREEN"), TEXT("Virtual screen x origin"), SM_YVIRTUALSCREEN, TEXT("SM_YVIRTUALSCREEN"), TEXT("Virtual screen y origin"), SM_CXVIRTUALSCREEN, TEXT("SM_CXVIRTUALSCREEN"), TEXT("Virtual screen width"), SM_CYVIRTUALSCREEN, TEXT("SM_CYVIRTUALSCREEN"), TEXT("Virtual screen height"), SM_CMONITORS, TEXT("SM_CMONITORS"), TEXT("Number of monitors"), SM_SAMEDISPLAYFORMAT, TEXT("SM_SAMEDISPLAYFORMAT"), TEXT("Same color format flag") };