(1)首先创建主窗口时,在其属性中加上:WS_HSCROLL:hwnd = CreateWindow (szAppName, TEXT ("Button Look"), WS_OVERLAPPEDWINDOW | WS_HSCROLL | WS_VSCROLL,//WS_HSCROLL表示有滚动条 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL) ;//hwnd为主窗口
(2)响应WM_VSCROLL消息,在其中调用SetScrollPos()设置滚动条本身的位置,还要调用ScrollWindow()来改变使窗口中的内容滚动(如窗口中的按钮等控件,它们也会上下移动):case WM_VSCROLL : switch (LOWORD (wParam)) { case SB_LINEDOWN : iScroll_y += 10; iDir= 1; break ;
case SB_LINEUP : croll_y -= 10;
iDir= -1; break ; } SetScrollPos ( hwnd, SB_VERT, iScroll_y, TRUE) ; InvalidateRect (hwnd, NULL, TRUE) ; //ScrollWindow()可滚动窗口,窗口中客户区的内容会移动 ScrollWindow( hwnd, 0, -10* iDir, NULL, NULL ); return 0 ;
注:本程序是在windows程序设计 第5版中创建动态按钮的代码中修改而来,只是作为测试,会有bug.
全部代码如下:
#include <windows.h>
struct{ int iStyle ; TCHAR * szText ;}button[] ={ BS_PUSHBUTTON, TEXT ("PUSHBUTTON"), BS_DEFPUSHBUTTON, TEXT ("DEFPUSHBUTTON"), BS_CHECKBOX, TEXT ("CHECKBOX"), BS_AUTOCHECKBOX, TEXT ("AUTOCHECKBOX"), BS_RADIOBUTTON, TEXT ("RADIOBUTTON"), BS_3STATE, TEXT ("3STATE"), BS_AUTO3STATE, TEXT ("AUTO3STATE"), BS_GROUPBOX, TEXT ("GROUPBOX"), BS_AUTORADIOBUTTON, TEXT ("AUTORADIO"), BS_OWNERDRAW, TEXT ("OWNERDRAW")} ;
#define NUM (sizeof button / sizeof button[0])
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
static int iScroll_y= 100;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow){ static TCHAR szAppName[] = TEXT ("BtnLook") ; HWND hwnd ; MSG msg ; WNDCLASS wndclass ; wndclass.style = CS_HREDRAW | CS_VREDRAW ; wndclass.lpfnWndProc = WndProc ; wndclass.cbClsExtra = 0 ; wndclass.cbWndExtra = 0 ; wndclass.hInstance = hInstance ; wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ; wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ; wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ; wndclass.lpszMenuName = NULL ; wndclass.lpszClassName = szAppName ; if (!RegisterClass (&wndclass)) { MessageBox (NULL, TEXT ("This program requires Windows NT!"), szAppName, MB_ICONERROR) ; return 0 ; } hwnd = CreateWindow (szAppName, TEXT ("Button Look"), WS_OVERLAPPEDWINDOW | WS_HSCROLL | WS_VSCROLL , CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, iCmdShow) ; UpdateWindow (hwnd) ; while (GetMessage (&msg, NULL, 0, 0)) { TranslateMessage (&msg) ; DispatchMessage (&msg) ; } return msg.wParam ;}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){ static HWND hwndButton[NUM] ; static RECT rect ; static TCHAR szTop[] = TEXT ("message wParam lParam"), szUnd[] = TEXT ("_______ ______ ______"), szFormat[] = TEXT ("%-16sX-X X-X"), szBuffer[50] ; static int cxChar, cyChar ; HDC hdc ; PAINTSTRUCT ps ; int i ; static int iDir= 1; switch (message) { case WM_CREATE : cxChar = LOWORD (GetDialogBaseUnits ()) ; cyChar = HIWORD (GetDialogBaseUnits ()) ; //创建动态按钮 for (i = 0 ; i < NUM ; i++) hwndButton[i] = CreateWindow ( TEXT("button"), button[i].szText, WS_CHILD | WS_VISIBLE | button[i].iStyle, cxChar, cyChar * (1 + 2 * i) * 6, 20 * cxChar, 7 * cyChar / 4, hwnd, (HMENU) i,//i为按钮的ID号 ((LPCREATESTRUCT) lParam)->hInstance, NULL) ; return 0 ;
case WM_SIZE : rect.left = 24 * cxChar ; rect.top = 2 * cyChar ; rect.right = LOWORD (lParam) ; rect.bottom = HIWORD (lParam) ; return 0 ; case WM_PAINT : InvalidateRect (hwnd, &rect, TRUE) ; hdc = BeginPaint (hwnd, &ps) ; SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)) ; SetBkMode (hdc, TRANSPARENT) ; TextOut (hdc, 24 * cxChar, cyChar, szTop, lstrlen (szTop)) ; TextOut (hdc, 24 * cxChar, cyChar, szUnd, lstrlen (szUnd)) ; EndPaint (hwnd, &ps) ; return 0 ; case WM_DRAWITEM : case WM_COMMAND ://按钮事件 ScrollWindow (hwnd, 0, -cyChar, &rect, &rect) ; hdc = GetDC (hwnd) ; SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)) ; TextOut (hdc, 24 * cxChar, cyChar * (rect.bottom / cyChar - 1), szBuffer, wsprintf (szBuffer, szFormat, message == WM_DRAWITEM ? TEXT ("WM_DRAWITEM") : TEXT ("WM_COMMAND"), HIWORD (wParam), LOWORD (wParam), HIWORD (lParam), LOWORD (lParam))) ;
//按钮的响应事件 //if ( wParam == BS_PUSHBUTTON) if ( LOWORD( wParam )== 0)//按钮的ID号
{ MessageBox( hwnd, TEXT("123"), TEXT("456"), 0); } ReleaseDC (hwnd, hdc) ; ValidateRect (hwnd, &rect) ; break ; case WM_DESTROY : PostQuitMessage (0) ; return 0 ;
case WM_VSCROLL : //int i = GetWindowLong ((HWND) lParam, GWL_ID) ; switch (LOWORD (wParam)) { // fall through case SB_LINEDOWN : //MessageBox( hwnd, TEXT("down"), TEXT("down456"), 0); iScroll_y += 10; iDir= 1; break ; // fall through case SB_LINEUP : //MessageBox( hwnd, TEXT("up"), TEXT("up456"), 0); iScroll_y -= 10;
iDir= -1; break ; } SetScrollPos ( hwnd, SB_VERT, iScroll_y, TRUE) ; InvalidateRect (hwnd, NULL, TRUE) ;
ScrollWindow( hwnd, 0, -10* iDir, NULL, NULL );//ScrollWindow()可滚动窗口,窗口中客户区的内容会移动 return 0 ; } return DefWindowProc (hwnd, message, wParam, lParam) ;}