Windows Mobile 编程 (Win32) - 输出文本
《Windows 程序设计》第四章主要介绍在窗口中显示文本相关知识。示例代码量很大,但实际上是一个实例不断升级的三个版本。
SysMets1:在窗口中输出文本的基本代码;
SysMets2:在上一个实例的基础上,加入纵向滚动条;
SysMets3:加入横、纵两个方向的滚动条;
这三个版本的代码使用了共同的一个SysMets.h头文件。下面是详细代码:
//SysMets.h #define NUMLINES ((int)(sizeof sysmetrics / sizeof sysmetrics[0])) struct { int iIndex; TCHAR * szLabel; TCHAR * szDesc; } sysmetrics [] = { SM_CMONITORS, TEXT("SM_CMONITORS"), TEXT("Number of monitors"), SM_CXBORDER, TEXT("SM_CXBORDER"), TEXT("Window border width"), SM_CYBORDER, TEXT("SM_CYBORDER"), TEXT("Window border height"), SM_CXDOUBLECLK, TEXT("SM_CXDOUBLECLK"), TEXT("Double click x tolerance"), SM_CYDOUBLECLK, TEXT("SM_CYDOUBLECLK"), TEXT("Double click y tolerance"), SM_CXEDGE, TEXT("SM_CXEDGE"), TEXT("3-D border width"), SM_CYEDGE, TEXT("SM_CYEDGE"), TEXT("3-D border height"), SM_CXFIXEDFRAME, TEXT("SM_CXFIXEDFRAME"), TEXT("Dialog window frame width"), SM_CYFIXEDFRAME, TEXT("SM_CYFIXEDFRAME"), TEXT("Dialog window frame height"), SM_CXHSCROLL, TEXT("SM_CXHSCROLL"), TEXT("Horizontal scroll arrow width"), SM_CYVSCROLL, TEXT("SM_CYVSCROLL"), TEXT("Vertical scroll arrow height"), SM_CXICON, TEXT("SM_CXICON"), TEXT("Icon width"), SM_CYICON, TEXT("SM_CYICON"), TEXT("Icon height"), SM_CXICONSPACING, TEXT("SM_CXICONSPACING"), TEXT("Horizontal icon spacing"), SM_CYICONSPACING, TEXT("SM_CYICONSPACING"), TEXT("Vertical icon spacing"), SM_CXSCREEN, TEXT("SM_CXSCREEN"), TEXT("Screen width in pixels"), SM_CYSCREEN, TEXT("SM_CYSCREEN"), TEXT("Screen height in pixels"), SM_CXSMICON, TEXT("SM_CXSMICON"), TEXT("Small icon width"), SM_CYSMICON, TEXT("SM_CYSMICON"), TEXT("Small icon height"), SM_CXVIRTUALSCREEN, TEXT("SM_CXVIRTUALSCREEN"), TEXT("Virtual screen width"), SM_CYVIRTUALSCREEN, TEXT("SM_CYVIRTUALSCREEN"), TEXT("Virtual screen height"), 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_CYMENU, TEXT("SM_CYMENU"), TEXT("Menu bar height"), SM_DEBUG, TEXT("SM_DEBUG"), TEXT("Debug version flag"), SM_SAMEDISPLAYFORMAT, TEXT("SM_SAMEDISPLAYFORMAT"), TEXT("Same color format flag"), SM_XVIRTUALSCREEN, TEXT("SM_XVIRTUALSCREEN"), TEXT("Virtual screen x origin"), SM_YVIRTUALSCREEN, TEXT("SM_YVIRTUALSCREEN"), TEXT("Virtual screen y origin"), SM_CXFULLSCREEN, TEXT("SM_CXFULLSCREEN"), TEXT("Full screen client area width"), SM_CYFULLSCREEN, TEXT("SM_CYFULLSCREEN"), TEXT("Full screen client area height"), SM_MOUSEPRESENT, TEXT("SM_MOUSEPRESENT"), TEXT("Mouse present flag") };
// SysMets1.c #include <windows.h> #include "sysmets.h" LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { static TCHAR szAppName[] = TEXT("SysMets1"); HWND hwnd; MSG msg; WNDCLASS wc; // Set up the window class description ZeroMemory(&wc, sizeof(wc)); wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WndProc; wc.hInstance = hInstance; wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wc.lpszClassName = szAppName; if (!RegisterClass(&wc)) { MessageBox(NULL, TEXT("RegisterClass() failed!"), szAppName, MB_ICONERROR); return 0; } hwnd = CreateWindow(szAppName, // window class name TEXT("Get System Metrics No. 1"), // window caption WS_OVERLAPPED | WS_SYSMENU, // window style CW_USEDEFAULT, // initial x position CW_USEDEFAULT, // initial y position CW_USEDEFAULT, // initial x size CW_USEDEFAULT, // initial y size NULL, // parent window handle NULL, // window menu handle hInstance, // program instance handle NULL); // creation parameters if (hwnd == NULL) { MessageBox(NULL, TEXT("CreateWindow() failed!"), szAppName, MB_ICONERROR); return 0; } ShowWindow(hwnd, nCmdShow); UpdateWindow(hwnd); while(GetMessage(&msg, NULL, 0, 0) > 0) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static int cxChar, cxCaps, cyChar; HDC hdc; int i; PAINTSTRUCT ps; TCHAR szBuffer[10]; TEXTMETRIC tm; switch (message) { case WM_CREATE: hdc = GetDC(hwnd); GetTextMetrics(hdc, &tm); cxChar = tm.tmAveCharWidth; cxCaps = (tm.tmPitchAndFamily & 1 ? 3 : 2) * cxChar / 2; cyChar = tm.tmHeight + tm.tmExternalLeading; ReleaseDC(hwnd, hdc); return 0; case WM_PAINT: hdc = BeginPaint(hwnd, &ps); for(i = 0; i < NUMLINES; i++) { ExtTextOut(hdc, 4, cyChar * i * 3, 0, NULL, sysmetrics[i].szLabel, lstrlen(sysmetrics[i].szLabel), NULL); ExtTextOut(hdc, 4, cyChar * (i * 3 + 1), 0, NULL, sysmetrics[i].szDesc, lstrlen(sysmetrics[i].szDesc), NULL); SetTextAlign(hdc, TA_RIGHT | TA_TOP); ExtTextOut(hdc, cxChar * 47, cyChar * (i * 3 + 1), 0, NULL, szBuffer, wsprintf(szBuffer, TEXT("%5d"), GetSystemMetrics(sysmetrics[i].iIndex)), NULL); SetTextAlign (hdc, TA_LEFT | TA_TOP) ; } EndPaint(hwnd, &ps); return 0; case WM_DESTROY: PostQuitMessage(0); return 0 ; } return DefWindowProc(hwnd, message, wParam, lParam); }
// SysMets2.c #include <windows.h> #include "sysmets.h" LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { static TCHAR szAppName[] = TEXT("SysMets2"); HWND hwnd; MSG msg; WNDCLASS wc; // Set up the window class description ZeroMemory(&wc, sizeof(wc)); wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WndProc; wc.hInstance = hInstance; wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wc.lpszClassName = szAppName; if (!RegisterClass(&wc)) { MessageBox(NULL, TEXT("RegisterClass() failed!"), szAppName, MB_ICONERROR); return 0; } hwnd = CreateWindow(szAppName, // window class name TEXT("Get System Metrics No. 2"), // window caption WS_OVERLAPPED | WS_SYSMENU, // window style CW_USEDEFAULT, // initial x position CW_USEDEFAULT, // initial y position CW_USEDEFAULT, // initial x size CW_USEDEFAULT, // initial y size NULL, // parent window handle NULL, // window menu handle hInstance, // program instance handle NULL); // creation parameters if (hwnd == NULL) { MessageBox(NULL, TEXT("CreateWindow() failed!"), szAppName, MB_ICONERROR); return 0; } ShowWindow(hwnd, nCmdShow); UpdateWindow(hwnd); while(GetMessage(&msg, NULL, 0, 0) > 0) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static int cxChar, cxCaps, cyChar, cyClient, iVscrollPos; HDC hdc; int i, y; PAINTSTRUCT ps; TCHAR szBuffer[10]; TEXTMETRIC tm; switch (message) { case WM_CREATE: hdc = GetDC(hwnd); GetTextMetrics(hdc, &tm); cxChar = tm.tmAveCharWidth; cxCaps = (tm.tmPitchAndFamily & 1 ? 3 : 2) * cxChar / 2; cyChar = tm.tmHeight + tm.tmExternalLeading; ReleaseDC(hwnd, hdc); SetScrollRange(hwnd, SB_VERT, 0, NUMLINES * 3 - 2, FALSE); SetScrollPos(hwnd, SB_VERT, iVscrollPos, TRUE); return 0; case WM_SIZE: cyClient = HIWORD(lParam); return 0; case WM_VSCROLL: switch(LOWORD(wParam)) { case SB_LINEUP: iVscrollPos -= 1; break; case SB_LINEDOWN: iVscrollPos += 1; break; case SB_PAGEUP: iVscrollPos -= cyClient / cyChar; break; case SB_PAGEDOWN: iVscrollPos += cyClient / cyChar; break; case SB_THUMBPOSITION: iVscrollPos = HIWORD(wParam); break; default: break; } iVscrollPos = max(0, min(iVscrollPos, NUMLINES * 3 - 2)); SCROLLINFO si; ZeroMemory(&si, sizeof(SCROLLINFO)); si.cbSize = sizeof(SCROLLINFO); si.fMask = SIF_POS; if (!GetScrollInfo(hwnd, SB_HORZ, &si)) { return 0; } //if (iVscrollPos != si.nPos) //{ SetScrollPos(hwnd, SB_VERT, iVscrollPos, TRUE); InvalidateRect(hwnd, NULL, TRUE); //} return 0; case WM_PAINT: hdc = BeginPaint(hwnd, &ps); for(i = 0; i < NUMLINES; i++) { y = cyChar * (i - iVscrollPos); ExtTextOut(hdc, 4, cyChar * (i * 3 - iVscrollPos), 0, NULL, sysmetrics[i].szLabel, lstrlen(sysmetrics[i].szLabel), NULL); ExtTextOut(hdc, 4, cyChar * (i * 3 + 1 - iVscrollPos), 0, NULL, sysmetrics[i].szDesc, lstrlen(sysmetrics[i].szDesc), NULL); SetTextAlign(hdc, TA_RIGHT | TA_TOP); ExtTextOut(hdc, cxChar * 44, cyChar * (i * 3 + 1 - iVscrollPos), 0, NULL, szBuffer, wsprintf(szBuffer, TEXT("%5d"), GetSystemMetrics(sysmetrics[i].iIndex)), NULL); SetTextAlign (hdc, TA_LEFT | TA_TOP) ; } EndPaint(hwnd, &ps); return 0; case WM_DESTROY: PostQuitMessage(0); return 0 ; } return DefWindowProc(hwnd, message, wParam, lParam); }
// SysMets3.c #include <windows.h> #include "sysmets.h" LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { static TCHAR szAppName[] = TEXT("SysMets3"); HWND hwnd; MSG msg; WNDCLASS wc; // Set up the window class description ZeroMemory(&wc, sizeof(wc)); wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WndProc; wc.hInstance = hInstance; wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wc.lpszClassName = szAppName; if (!RegisterClass(&wc)) { MessageBox(NULL, TEXT("RegisterClass() failed!"), szAppName, MB_ICONERROR); return 0; } hwnd = CreateWindow(szAppName, // window class name TEXT("Get System Metrics No. 3"), // window caption WS_OVERLAPPED | WS_SYSMENU, // window style CW_USEDEFAULT, // initial x position CW_USEDEFAULT, // initial y position CW_USEDEFAULT, // initial x size CW_USEDEFAULT, // initial y size NULL, // parent window handle NULL, // window menu handle hInstance, // program instance handle NULL); // creation parameters if (hwnd == NULL) { MessageBox(NULL, TEXT("CreateWindow() failed!"), szAppName, MB_ICONERROR); return 0; } ShowWindow(hwnd, nCmdShow); UpdateWindow(hwnd); while(GetMessage(&msg, NULL, 0, 0) > 0) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static int cxChar, cxCaps, cyChar, cxClient, cyClient, iMaxWidth; HDC hdc; int i, x, y, iVertPos, iHorzPos, iPaintBeg, iPaintEnd; PAINTSTRUCT ps; SCROLLINFO si; TCHAR szBuffer[10]; TEXTMETRIC tm; switch (message) { case WM_CREATE: hdc = GetDC(hwnd); GetTextMetrics(hdc, &tm); cxChar = tm.tmAveCharWidth; cxCaps = (tm.tmPitchAndFamily & 1 ? 3 : 2) * cxChar / 2; cyChar = tm.tmHeight + tm.tmExternalLeading; ReleaseDC(hwnd, hdc); // Save the width of the three columns iMaxWidth = 40 * cxChar + 22 * cxCaps; return 0; case WM_SIZE: cxClient = LOWORD(lParam); cyClient = HIWORD(lParam); // Set vertical scroll bar range and page size si.cbSize = sizeof(si); si.fMask = SIF_RANGE | SIF_PAGE; si.nMin = 0; si.nMax = NUMLINES - 1; si.nPage = cyClient / cyChar; SetScrollInfo(hwnd, SB_VERT, &si, TRUE); // Set horizontal scroll bar range and page size si.cbSize = sizeof(si); si.fMask = SIF_RANGE | SIF_PAGE; si.nMin = 0; si.nMax = 2 + iMaxWidth / cxChar; si.nPage = cxClient / cxChar; SetScrollInfo(hwnd, SB_HORZ, &si, TRUE); return 0; case WM_VSCROLL: // Get all the vertial scroll bar information si.cbSize = sizeof(si); si.fMask = SIF_ALL; GetScrollInfo(hwnd, SB_VERT, &si); // Save the position for comparison later on iVertPos = si.nPos; switch(LOWORD(wParam)) { case SB_TOP: si.nPos = si.nMin; break ; case SB_BOTTOM: si.nPos = si.nMax; break; case SB_LINEUP: si.nPos -= 1; break; case SB_LINEDOWN: si.nPos += 1; break; case SB_PAGEUP: si.nPos -= si.nPage; break; case SB_PAGEDOWN: si.nPos += si.nPage; break; case SB_THUMBPOSITION: si.nPos = si.nTrackPos; break; default: break; } // Set the position and then retrieve it. Due to adjustments // by Windows it may not be the same as the value set. si.fMask = SIF_POS; SetScrollInfo(hwnd, SB_VERT, &si, TRUE); GetScrollInfo(hwnd, SB_VERT, &si); // If the position has changed, scroll the window and update it if (si.nPos != iVertPos) { ScrollWindowEx(hwnd, 0, cyChar * (iVertPos - si.nPos), NULL, NULL, NULL, NULL, SW_INVALIDATE); InvalidateRect(hwnd, NULL, TRUE); } return 0; case WM_HSCROLL: // Get all the vertial scroll bar information si.cbSize = sizeof(si); si.fMask = SIF_ALL; // Save the position for comparison later on GetScrollInfo(hwnd, SB_HORZ, &si); iHorzPos = si.nPos; switch (LOWORD(wParam)) { case SB_LINELEFT: si.nPos -= 1; break; case SB_LINERIGHT: si.nPos += 1; break; case SB_PAGELEFT: si.nPos -= si.nPage; break; case SB_PAGERIGHT: si.nPos += si.nPage; break; case SB_THUMBPOSITION: si.nPos = si.nTrackPos; break; default: break; } // Set the position and then retrieve it. Due to adjustments // by Windows it may not be the same as the value set. si.fMask = SIF_POS; SetScrollInfo(hwnd, SB_HORZ, &si, TRUE); GetScrollInfo(hwnd, SB_HORZ, &si); // If the position has changed, scroll the window if (si.nPos != iHorzPos) { ScrollWindowEx(hwnd, cxChar * (iHorzPos - si.nPos), 0, NULL, NULL, NULL, NULL, SW_INVALIDATE); InvalidateRect(hwnd, NULL, TRUE); } return 0; case WM_PAINT: hdc = BeginPaint(hwnd, &ps); // Get vertical scroll bar position si.cbSize = sizeof(si); si.fMask = SIF_POS; GetScrollInfo(hwnd, SB_VERT, &si); iVertPos = si.nPos; // Get horizontal scroll bar position GetScrollInfo(hwnd, SB_HORZ, &si); iHorzPos = si.nPos; // Find painting limits iPaintBeg = max(0, iVertPos + ps.rcPaint.top / cyChar); iPaintEnd = min(NUMLINES - 1, iVertPos + ps.rcPaint.bottom / cyChar); for(i = iPaintBeg; i < iPaintEnd; i++) { x = cxChar * (1 - iHorzPos); y = cyChar * (i - iVertPos); ExtTextOut(hdc, x, y, 0, NULL, sysmetrics[i].szLabel, lstrlen(sysmetrics[i].szLabel), NULL); ExtTextOut(hdc, x + 22 * cxCaps, y, 0, NULL, sysmetrics[i].szDesc, lstrlen(sysmetrics[i].szDesc), NULL); SetTextAlign(hdc, TA_RIGHT | TA_TOP); ExtTextOut(hdc, x + 22 * cxCaps + 40 * cxChar, y, 0, NULL, szBuffer, wsprintf(szBuffer, TEXT("%5d"), GetSystemMetrics(sysmetrics[i].iIndex)), NULL); SetTextAlign (hdc, TA_LEFT | TA_TOP) ; } EndPaint(hwnd, &ps); return 0; case WM_DESTROY: PostQuitMessage(0); return 0 ; } return DefWindowProc(hwnd, message, wParam, lParam); }
因为我是在Windows Mobile平台上实验的这些代码,所以与Windows平台稍有不同。
比如:GetSystemMetrics()函数在Windows Mobile平台上所能获得到的信息,相比Windows平台少很多;另外Windows Mobile平台不支持TextOut()和ScrollWindow()函数,需要更换为对应加强版函数ExtTextOut()和ScrollWindowEx()。
另外,还要考虑到Windows Mobile设置的屏幕大小问题。
优质内容筛选与推荐>>