windows学习记录----滚动条、GDI基础
1.滚动条
1 #include<windows.h> 2 #include"text.h" 3 4 LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM ) ; //声明窗口过程函数 5 6 int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow ) 7{ 8static TCHAR szAppName[] = TEXT("LearnScroll") ; 9 HWND hwnd ; 10 MSG msg ; 11 WNDCLASS wndclass ; 12 13//窗口类成员属性 14 wndclass.lpfnWndProc = WndProc ; 15 wndclass.style = CS_HREDRAW | CS_VREDRAW ; 16 wndclass.hInstance = hInstance ; 17 wndclass.lpszClassName = szAppName ; 18 wndclass.lpszMenuName = NULL ; 19 wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH) ; 20 wndclass.hCursor = LoadCursor(NULL, IDI_APPLICATION) ; 21 wndclass.hIcon = LoadIcon(NULL, IDC_ARROW) ; 22 wndclass.cbClsExtra = 0 ; 23 wndclass.cbWndExtra = 0 ; 24 25//注册窗口类 26if( !RegisterClass(&wndclass) ) 27 { 28 MessageBox( NULL, TEXT("无法注册窗口类!"), TEXT("错误"), MB_OK | MB_ICONERROR ) ; 29return0 ; 30 } 31 32//创建窗口 33 hwnd = CreateWindow( 34 szAppName, TEXT("滚动条示例"), 35 WS_OVERLAPPEDWINDOW | WS_VSCROLL | WS_HSCROLL, 36 CW_USEDEFAULT, CW_USEDEFAULT, 37 CW_USEDEFAULT, CW_USEDEFAULT, 38 NULL, NULL, hInstance, NULL 39 ) ; 40 41//显示窗口 42 ShowWindow( hwnd, iCmdShow ) ; 43 UpdateWindow( hwnd ) ; 44 45//获取、翻译、分发消息 46while( GetMessage( &msg, NULL, 0, 0 ) ) 47 { 48 TranslateMessage( &msg ) ; 49 DispatchMessage( &msg ) ; 50 } 51 52return msg.wParam ; 53} 54
1 LRESULT CALLBACK WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam ) 2{ 3staticint cxChar, cxCaps, cyChar, cyClient, cxClient, iVscrollPos, iHscrollPos ; 4//cxChar:平均字符宽度; cxCaps: 大写字母平均宽度; cyChar: 字符高; cyClient、cxClient: 客户区y、x方向尺寸; 5//iVscrollPos: 竖直方向滚动条滑块位置; iHscrollPos: 水平方向滚动条滑块位置 6 HDC hdc ; 7 RECT rect ; //记录客户区RECT结构 8int i, x, y; //i循环控制, x记录水平方向坐标, y竖直方向坐标 9 PAINTSTRUCT ps ; 10 TEXTMETRIC tm ; 11 SCROLLINFO si ; //SCROLLINFO结构对象 12int iMaxLength ; //所有语句中的最大长度 13 14 iMaxLength = GetMaxLength() ; //取得最大长度 15 16switch(message) 17 { 18case WM_CREATE: //处理WM_CREATE消息 19 hdc = GetDC(hwnd) ; 20 GetTextMetrics( hdc, &tm ) ; //获取系统字体信息 21 cxChar = tm.tmAveCharWidth ; //获取平均宽度 22 cxCaps = (tm.tmPitchAndFamily & 1 ? 3 : 2) * cxChar / 2 ; //大写字母平均宽度 23 cyChar = tm.tmHeight + tm.tmExternalLeading ; //字符高度 24 ReleaseDC( hwnd, hdc ); 25 26return0 ; 27 28case WM_SIZE: //处理WM_SIZE 29 GetClientRect( hwnd, &rect ) ; 30 cxClient = LOWORD (lParam) ; 31 cyClient = HIWORD (lParam) ; 32 33//设置垂直滚动条相关参数 34 si.cbSize = sizeof (si) ; 35 si.fMask = SIF_RANGE | SIF_PAGE ; 36 si.nMin = 0 ; 37 si.nMax = NUMLINES - 1 ; 38 si.nPage = cyClient / cyChar ; 39 SetScrollInfo(hwnd, SB_VERT, &si, TRUE) ; 40 41//设置水平滚动条相关参数 42 si.cbSize = sizeof (si) ; 43 si.fMask = SIF_RANGE | SIF_PAGE ; 44 si.nMin = 0 ; 45 si.nMax = 2 + iMaxLength ; 46 si.nPage = cxClient / cxCaps ; 47 SetScrollInfo(hwnd, SB_HORZ, &si, TRUE) ; 48 49return0; 50 51case WM_VSCROLL: //处理垂直滚动条消息 52 si.cbSize = sizeof (si) ; 53 si.fMask = SIF_ALL ; 54 GetScrollInfo(hwnd, SB_VERT, &si) ; 55 56 iVscrollPos = si.nPos ; //记录当前滑块位置 57 58switch( LOWORD(wParam) ) //处理滚动条消息 59 { 60case SB_TOP: //到达顶部 61 si.nPos = si.nMin ; 62break ; 63 64case SB_BOTTOM: //到达底部 65 si.nPos = si.nMax ; 66break ; 67 68case SB_LINEUP: //上翻一行 69 si.nPos -= 1 ; 70break ; 71 72case SB_LINEDOWN: //下翻一行 73 si.nPos += 1 ; 74break ; 75 76case SB_PAGEUP: //向上翻一整页 77 si.nPos -= si.nPage ; 78break ; 79 80case SB_PAGEDOWN: //向下翻一整页 81 si.nPos += si.nPage ; 82break ; 83 84case SB_THUMBTRACK: //移动滑块时 85 si.nPos = si.nTrackPos ; 86break ; 87 88default: 89break; 90 } 91 si.fMask = SIF_POS ; 92 SetScrollInfo(hwnd, SB_VERT, &si, TRUE) ; //重置滑块位置 93 GetScrollInfo(hwnd, SB_VERT, &si) ; 94if( si.nPos != iVscrollPos ) 95 { 96 ScrollWindow(hwnd, 0, cyChar * (iVscrollPos - si.nPos), NULL, NULL) ; //滚动内容 97 UpdateWindow(hwnd) ; 98 } 99return0 ; 100 101case WM_HSCROLL: //处理水平滚动条消息 102 si.cbSize = sizeof (si) ; 103 si.fMask = SIF_ALL ; 104 GetScrollInfo (hwnd, SB_HORZ, &si) ; 105 106 iHscrollPos = si.nPos ; //记录当前滑块位置 107switch( LOWORD(wParam) ) 108 { 109case SB_TOP: //到达顶部 110 si.nPos = si.nMin ; 111break ; 112 113case SB_BOTTOM: //到达底部 114 si.nPos = si.nMax ; 115break ; 116 117case SB_LINELEFT: //左翻一行 118 si.nPos -= 1 ; 119break ; 120 121case SB_LINERIGHT: //右翻一行 122 si.nPos += 1 ; 123break ; 124 125case SB_PAGELEFT: //左翻一页 126 si.nPos -= si.nPage ; 127break ; 128 129case SB_PAGERIGHT: //右翻一页 130 si.nPos += si.nPage ; 131break ; 132 133case SB_THUMBTRACK: //移动滑块时 134 si.nPos = si.nTrackPos ; 135break ; 136 137default: 138break ; 139 } 140 si.fMask = SIF_POS ; 141 SetScrollInfo(hwnd, SB_HORZ, &si, TRUE) ; //重置滑块位置 142 GetScrollInfo(hwnd, SB_HORZ, &si) ; 143if( si.nPos != iHscrollPos ) 144 { 145 ScrollWindow(hwnd, cxCaps * (iHscrollPos - si.nPos), 0, NULL, NULL) ; //滚动内容 146 UpdateWindow(hwnd) ; 147 } 148return0 ; 149 150case WM_PAINT: //处理WM_PAINT消息 151 hdc = BeginPaint( hwnd, &ps ) ; 152 153 si.cbSize = sizeof (si) ; 154 si.fMask = SIF_POS ; 155 GetScrollInfo(hwnd, SB_VERT, &si) ; 156 iVscrollPos = si.nPos ; //获取当前垂直滑块位置 157 158 GetScrollInfo(hwnd, SB_HORZ, &si) ; 159 iHscrollPos = si.nPos ; //获取当前水平滑块位置 160 161for( i= 0; i < NUMLINES; i++ ) 162 { 163 y = cyChar * ( i - iVscrollPos ) ; 164 x = cxCaps * ( 0 - iHscrollPos ) ; 165 TextOut( hdc, x, y, statement[i], lstrlen(statement[i]) ) ; //输出文字 166 } 167 168 EndPaint( hwnd, &ps ) ; 169return0 ; 170 171case WM_DESTROY: //处理WM_DESTROY消息 172 PostQuitMessage( 0 ) ; 173return0 ; 174 } 175 176return DefWindowProc( hwnd, message, wParam, lParam ) ; 177 }
1>. SetScrollInfo
函数功能: 用于设置滚动条的相关参数, 包括滚动范围的最大值和最小值, 页面大小, 滑块的位置, 函数的原型:
int SetScrollInfo( HWND hWnd; //窗口句柄 int fnBar, //指定被设定参数的滚动条的类型 LPSCROLLINFO lpsi, //指向一个SCROLLINFO结构 BOOL fRedraw //重绘标志 ) ;
SCROLLINFO的成员记录有关滚动条的信息, 其结构定义如下:
typedef struct tagSCROLLINFO { UINT cbSize ; //设置为sizeof (SCROLLINFO), 表示该结构的大小 UINT fMask ; //要设置或获取的值 int nMin ; //滚动条范围的最小值 int nMax ; //滚动条范围的最大值 UINT nPage ; //页面大小 int nPos ; //当前位置 int nTrackPos ; //当前追踪位置 }SCROLLINFO; 成员一UINT cbSize : 该参数必须在函数调用之前设置, cbSize表示该结构的大小, 用sizeof (SCROLLINFO)表示即可。 成员二UINT fMask: 用于指定指定结构中的哪些成员是有效的, 通过位或运算进行组合, 可组合的标识符如下: SIF_ALL //整个结构都有效 SIF_DISABLENOSCROLL //禁用滚动条 SIF_PAGE //用于指定或获取页面的大小, 在SetScrollInfo中用于设定页面的大小, 在GetScrollInfo用于获取页面的大小 SIF_POS//设置/取得滚动条滑块当前的位置 SIF_RANGE//滚动条的范围 SIF_TRACKPOS //仅在GetScrollInfo函数中使用, 并且仅用在处理SB_THUMBTRACK或者SB_THUMBPOSITION的WM_VSCROLL消息或WM_HSCROLL消息时使用。取得当前滑块的跟踪位置。
2>. GetScrollInfo
用于取得滚动条的相关参数, 包括滚动范围的最大值和最小值, 页面大小, 滑块的位置, 函数的原型:
BOOL GetScrollInfo( HWND hWnd, //窗口句柄 int fnBar, //指定被设定参数的滚动条的类型 LPSCROLLINFO lpsi //指向一个SCROLLINFO结构 );
3>. ScrollWindow
该函数的作用是滚动所指定的窗口客户区域内容, 原型如下:
BOOL ScrollWindow( HWND hWnd, //窗口句柄 int XAmount, //指定水平滚动的距离 int YAmount, //指定垂直滚动的距离 CONST RECT *IpRect, //指向RECT结构的指针, 该结构指定了将要滚动的客户区范围。若此参数为NULL,则整个客户区域将被滚动。 CONST RECT *lpClipRect //指向RECT结构的指针, 该结构指定了要滚动的裁剪区域。只有这个矩形中才会被滚动。
2.GDI基础
在诸多的GDI函数中从功能上来说实际上可以主要分为以下5种类型:
1>. 获取、释放设备环境的函数;
2>. 获取设备环境信息的函数;
3>. 绘图函数;
4>. 设置、获取设备环境属性的函数;
5>. 使用GDI"对象"的函数;
在屏幕上绘图的相关流程:
获取设备环境的句柄(当获取成功时就意味着你的应用程序有了在屏幕上绘图的权限)-----调用GDI中的绘图函数通过设备环境句柄对屏幕进行绘制------释放句柄。
获取设备环境句柄:
1>. 使用BeginPaint函数和EndPaint函数:
HDC BeginPaint( HWND hwnd, // 窗口的句柄 LPPAINTSTRUCT lpPaint // 绘制信息 );
2>. 使用GetDC函数
HDC GetDC( HWND hWnd ) ;
3>. 使用GetWindowDC
HDC GetWindowDC( HWND hWnd // 窗口句柄 );与GetDC不同, GetDC可以用来获取窗口的客户区部分的设备环境句柄, 而GetWindowDC是用来获取整个窗口的设备环境句柄, 整个窗口是指包括窗口的标题栏、菜单栏、滚动条、状态栏以及客户区和客户区的外缘边框部分
4>. 使用CreateDC
HDC CreateDC( LPCTSTR lpszDriver, LPCTSTR lpszDevice, LPCTSTR lpszOutput, const DEVMODE *lpInitData );
1LRESULT CALLBACK WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam ) 2{ 3 HDC hdc ; 4 PAINTSTRUCT ps ; 5 POINT apn[4] = { {150, 50}, {200, 200}, {150, 300}, {150, 500} } ; //坐标组 6 POINT apt[8] = { { 200, 50}, {300, 200}, {250, 200}, {200, 300}, {250, 300}, {300, 350}, {250, 400}, {250, 500} } ; //坐标组 7 DWORD lpPts[] = { 4, 4 }; //使用PolyPolyline进行多条折线绘制时的分组 8int i ; 9 10switch( message ) 11 { 12case WM_PAINT: 13 hdc = BeginPaint( hwnd, &ps ) ; 14 15//在(50, y)方向上绘制90个点, 颜色为黑色 16for( i = 0; i < 90; i++ ) 17 SetPixel( hdc, 50, 50 + i * 5, RGB( 0, 0, 0 ) ) ; 18 19//画线, 起点坐标( 100, 50 ), 终点坐标( 100, 500 ) 20 MoveToEx( hdc, 100, 50, NULL ); 21 LineTo( hdc, 100, 500 ); 22
23//画一条折线 24 Polyline( hdc, apn, 4 ) ; 25
26//画2条折线, 将apt分为2组 27 PolyPolyline( hdc, apt, lpPts, 2 ) ; 28 29//画椭圆弧线 30 Arc(hdc, 350, 50, 500, 500, 400, 100, 400, 500 ) ; 31 32//画矩形 33 Rectangle( hdc, 450, 50, 500, 500 ) ; 34 35 //画椭圆 36 Ellipse( hdc, 550, 50, 600, 500 ) ; 37 38 //画圆角矩形 39 RoundRect( hdc, 650, 50, 700, 500, 20, 20 ) ; 40 41 //画扇形 42 Pie( hdc, 750, 50, 850, 150, 850, 80, 850, 160 ) ; 43
44//画拱形 45 Chord( hdc, 750, 400, 850, 500, 850, 450, 750, 450 ) ; 46
47 EndPaint( hwnd, &ps ) ; 48return0 ; 49
50case WM_DESTROY: 51 PostQuitMessage( 0 ) ; 52return0 ; 53 } 54
55return DefWindowProc( hwnd, message, wParam, lParam ) ; 56 }