编程技术分享

分享一些我自己开发过程中的笔记

1,当下列情况发生时windows会发送WM_PAINT消息: 在使用者移动视窗或显示视窗时,视窗中先前被隐藏的区域重新可见。 使用者改变视窗的大小(如果视窗类别样式有著CS_HREDRAW和CS_VREDRAW位元旗标的设定)。 程式使用ScrollWindow或ScrollDC函式滚动显示区域的一部分。 程式使用InvalidateRect或InvalidateRgn函式刻意产生WM_PAINT讯息。 当对话框或者信息框被关闭 菜单被关闭 显示工具提示信息 2,下面的情况下不会发送WM_PAINT消息,windows会自动保存 鼠标箭头穿过显示区域 图标拖过显示区域 3,windows为每个程序保存一个绘图资讯结构,且windows不可能发送两个WM_PAINT结构 4,InvalidateRect可以让整个显示区域无效,GetUpdateRect可以获取无效举行的坐标,呼叫BeginPaint后,整个显示区域变为有效,ValidateRect可以让任意举行区域变为有效 5,TextOut (hdc, x, y, psText, iLength) ; 6,取得DC的第一种方法: 在回调函数中定义 PAINTSTRUCT ps ; 在处理WM_PAINT时先调用BeginPaint 他的第一个参数是窗口句柄,第二个是一个PAINTSTRUCT结构地址,返回值是HDC hdc ; case WM_PAINT: hdc = BeginPaint (hwnd, &ps) ; 处理代码; EndPaint (hwnd, &ps) ; break; 7,若不调用BeginPaint和EndPaint而直接return,windows会不断地发送WM_PAINT消息 8,PAINTSTRUCT的钱三个成员变量是有用的,第一个是hdc,第二个表示背景是否被擦除,如果被擦除则为FALSE否则为TRUE,第三个是rcPaint无效举行。 9,如果想在需要更新的举行外绘图,做以下呼叫 InvalidateRect (hwnd, NULL, TRUE) ; 10,获取dc的第二种方法 要得到视窗显示区域的装置内容代号,可以呼叫GetDC来取得代号,在使用完後呼叫ReleaseDC: hdc = GetDC (hwnd) ; 处理代码 ReleaseDC (hwnd, hdc) ; 必须成对出现 11,如果想使整个屏幕变为有效,则需要呼叫 ValidateRect (hwnd, NULL) ; 12,使用GetWindowDC可以获取整个窗口的设备描述表句柄,需要处理飞显示区域重绘(WM_NCPAINT)消息。 13,TEXTMETRIC结构用来描述字体资讯 要使用GetTextMetrics函式,需要先定义一个结构变数(通常称为tm): TEXTMETRIC tm ; 在需要确定文字大小时,先取得装置内容代号,再呼叫GetTextMetrics: hdc = GetDC (hwnd) ; GetTextMetrics (hdc, &tm) ; ReleaseDC (hwnd, hdc) ; 14,TEXTMETRIC的重要成员 LONG tmHeight; //字符高度 TEXTMETRIC结构字段的图示[1] LONG tmAscent; //字符上部高度(基线以上) LONG tmDescent; //字符下部高度(基线以下) LONG tmInternalLeading, //由tmHeight定义的字符高度的顶部空间数目 LONG tmExternalLeading, //夹在两行之间的空间数目 LONG tmAveCharWidth, //平均字符宽度 LONG tmMaxCharWidth, //最宽字符的宽度 由于windows启动后,字体就不会再更改了,所以建议在WM_CREATE中调用GetTextMetric函数。 14,应该先保存字元宽度和字元高度,通常在囘調函數中使用 static int cxChar, cyChar ; case WM_CREATE: hdc = GetDC (hwnd) ; GetTextMetrics (hdc, &tm) ; cxChar = tm.tmAveCharWidth ; cyChar = tm.tmHeight + tm.tmExternalLeading ; ReleaseDC (hwnd, hdc) ; 15,格式化字符序列 int iLength ; TCHAR szBuffer [40] ; 其他行程式 iLength = wsprintf (szBuffer, TEXT ("The sum of %i and %i is %i"), iA, iB, iA + iB) ; TextOut (hdc, x, y, szBuffer, iLength) ; 16,对於可变宽度字体,TEXTMETRIC结构中的tmPitchAndFamily栏位的低位元为1,对於固定宽度字体,该值为0。 17,SetTextAlign (hdc, TA_RIGHT | TA_TOP) ; 之後,传给後续TextOut函式的座标将指定字串的右上角,而不是左上角。 18,可以用GetClientRect函數獲取到視窗的大小,但是效率並不高,我們可以處理WM_SIZE(窗口大小被改變)消息,該消息的LPARAM低字組鐘存放寬度,高字節存放高度。 首先定義兩個靜態變量保存其大小 static int cxClient, cyClient ; 處理WM_SIZE消息的方法如下: case WM_SIZE: cxClient = LOWORD (lParam) ; cyClient = HIWORD (lParam) ; return 0 ; 用如下公式可以計算出在顯示區域顯示的總行數 cyClient / cyChar 用如下公式計算一橫排能顯示的字符數 cxClient / cxChar 19,只需要在CreateWindow的第三個參數增加關鍵字SW_VSCROLL就可以增加垂直滾動條;增加SW_HSCROLL就可以獲得平行滾動條 20,SetScrollRange (hwnd, iBar, iMin, iMax, bRedraw) ; 用來設置捲動列的數值 参数iBar为SB_VERT或者SB_HORZ,iMin和iMax分别是范围的最小值和最大值。如果想要Windows根据新范围重画卷动列,则设置bRedraw为TRUE(如果在呼叫SetScrollRange後,呼叫了影响卷动列位置的其他函式,则应该将bRedraw设定为FALSE以避免过多的重画)。 21,可以使用SetScrollPos設置滾動條的位置 SetScrollPos (hwnd, iBar, iPos, bRedraw) ; 22,如果需要使用滾動條,程序員需要做以下工作 初始化卷动列的范围和位置 处理视窗讯息处理程式的卷动列讯息 更新卷动列内卷动方块的位置 更改显示区域的内容以回应对卷动列的更改 23,在用滑鼠单击卷动列或者拖动卷动方块时,Windows给视窗讯息处理程式发送WM_VSCROLL(供上下移动)和WM_HSCROLL(供左右移动)讯息。 25,在wParam的低字组是SB_THUMBTRACK时,wParam的高字组是使用者在拖动卷动方块时的目前位置。该位置位於卷动列范围的最小值和最大值之间。 在wParam的低字组是SB_THUMBPOSITION时,wParam的高字组是使用者释放滑鼠键後卷动方块的最终位置。对於其他的卷动列操作,wParam的高字组应该被忽略。 26,如果您希望立即更新无效区域,可以在呼叫InvalidateRect之後呼叫UpdateWindow: UpdateWindow (hwnd) ; 27,SetScrollInfo (hwnd, iBar, &si, bRedraw) ; GetScrollInfo (hwnd, iBar, &si) ; 其中第三個參數通常定義為 SCROLLINFO si ; 使用之前需要: si.cbSize = sizeof (si) ; 或 si.cbSize = sizeof (SCROLLINFO) ; 顯示圖像 1,第三種獲得DC的方法 hdc = CreateDC (pszDriver, pszDevice, pszOutput, pData) ; 其他行程式 DeleteDC (hdc) ; 2,hdc = CreateIC (TEXT ("DISPLAY"), NULL, NULL, NULL) ; 不能寫入,只能獲取信息 3,可以用以下方法獲得顯示器或打印機的信息 iValue = GetDeviceCaps (hdc, iIndex) ; 4,Windows应用程式可以使用SM_CXSCREEN和SM_CYSCREEN参数从GetSystemMetrics得到图素尺寸。 5,如果使用如下的方式建立視窗,則dc不會改變 wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC ; 6,idSaved = SaveDC (hdc) ; 现在,可以改变一些属性,在想要回到呼叫SaveDC前存在的装置内容时,呼叫: RestoreDC (hdc, idSaved) ; 7,GetPixel函式传回指定座标处的图素颜色: crColor = GetPixel (hdc, x, y) ; SetPixel函式在指定的x和y座标以特定的颜色设定图素: SetPixel (hdc, x, y, crColor) ; 8,画一条直线,必须呼叫两个函式。第一个函式指定了线的开始点,第二个函式指定了线的终点: MoveToEx (hdc, xBeg, yBeg, NULL) ; LineTo (hdc, xEnd, yEnd) ; 9,目前位置就是開始點,如果想獲得,通過以下函數 POINT pt; GetCurrentPositionEx (hdc, &pt) ; 10,如果想把一個數組中的座標繪製成一條線,可以用 Polyline (hdc, apt, 5) ; 11,PolylineTo使用目前位置作为开始点,并将目前位置设定为最後一根线的终点。 MoveToEx (hdc, apt[0].x, apt[0].y, NULL) ; PolylineTo (hdc, apt + 1, 4) ; 12,使用下面的函数画一个矩形 Rectangle (hdc, xLeft, yTop, xRight, yBottom) ; 其中(xLeft, yTop)是矩形的左上角,(xRight, yBottom)是矩形的右下角。 13,使用下面的函数画一个椭圆 Ellipse (hdc, xLeft, yTop, xRight, yBottom) ; 14使用下面的函数画圆角矩形 RoundRect ( hdc, xLeft, yTop, xRight, yBottom, xCornerEllipse, yCornerEllipse) ; 如果xCornerEllipse等於xLeft与xRight的差,且yCornerEllipse等於yTop与yBottom的差,那么RoundRect函式将画出一个椭圆。 通常使用以下方法计算矩形的弧度 xCornerEllipse = (xRight - xLeft) / 4 ; yCornerEllipse = (yBottom- yTop) / 4 ; 15,下面依次为画椭圆线、椭圆的一部分(弓形)、扇形 Arc (hdc, xLeft, yTop, xRight, yBottom, xStart, yStart, xEnd, yEnd) ; Chord (hdc, xLeft, yTop, xRight, yBottom, xStart, yStart, xEnd, yEnd) ; Pie (hdc, xLeft, yTop, xRight, yBottom, xStart, yStart, xEnd, yEnd) ; 16,如果想画一条贝塞尔曲线可以调用下面的函数 POINT apt[4]; PolyBezier (hdc, apt, iCount) ; 或 PolyBezierTo (hdc, apt, iCount) ; iCount参数等於1加上您所绘制的这些首尾相接曲线条数的三倍。 17,可以使用以下方法定义一个画笔的句柄 HPEN hPen ; hPen = GetStockObject (WHITE_PEN) ; 就获得了一个白色的画笔。 使用 SelectObject (hdc, hPen) ; 可以将画笔选中设备上下文 SelectObject返回之前画笔的句柄 18,可以使用以下函数建立一个逻辑画笔: hPen = CreatePen (iPenStyle, iWidth, crColor) ; 19,如果想使用CreatePenIndirect应该先建立一个LOGPEN的结构 LOGPEN logpen ; 他有三个成员变量,就是CreatePen的三个参数 hPen = CreatePenIndirect (&logpen) ; 注意:必须在使用完画笔后,调用DeleteObject删除画笔 19,如果想获得某个画笔的信息可以调用 GetObject (hPen, sizeof (LOGPEN), (LPVOID) &logpen) ; 如果需要目前正在使用的画笔的句柄,可以调用 hPen = GetCurrentObject (hdc, OBJ_PEN) ; 20,您可以通过如下呼叫来改变Windows用来填入空隙的背景色: SetBkColor (hdc, crColor) ; 通过将背景模式转换为TRANSPARENT,可以阻止Windows填入空隙: SetBkMode (hdc, TRANSPARENT) ; 21,可以通过以下呼叫在装置内容中设定新的绘图模式: SetROP2 (hdc, iDrawMode) ; 23,选择画刷的步骤如下 1,建立画刷句柄 HBRUSH hBrush ; 2,呼叫GetStockObject得到一个现有的画刷句柄 hBrush = GetStockObject (GRAY_BRUSH) ; 3,呼叫SelectObject选入设备上下文 SelectObject (hdc, hBrush) ; 如果您想画一个没有边界框的图形 ,可以将NULL_PEN选进装置内容: 如果您想画出图形的边界框,但不填入内部,则将NULL_BRUSH选进装置内容: 24,画多边形 Polygon (hdc, apt, iCount) ; 绘制多个多边形 PolyPolygon (hdc, apt, aiCounts, iPolyCount) ; 使用下面的函数设置多边形的填入方式 SetPolyFillMode (hdc, iMode) ; 25,可以使用下面五个函数建立逻辑画刷 hBrush = CreateSolidBrush (crColor) ; hBrush = CreateHatchBrush (iHatchStyle, crColor) ; hBrush = CreateBrushIndirect (&logbrush) ; 26,可以用下面的方法设置映射方式: SetMapMode (hdc, iMapMode) ; 可以通过 iMapMode = GetMapMode (hdc) ; 获得当前的映射方式 27,下面的函数可以将装置点转换为逻辑点 DPtoLP (hdc, pPoints, iNumber) ; 下面的函式将逻辑点转换为装置点: LPtoDP (hdc, pPoints, iNumber) ; 例如,假设显示区域为cxClient个图素宽和cyClient个图素高。如果想将逻辑点(0,0)定义为显示区域的中心,可进行如下呼叫: SetViewportOrgEx (hdc, cxClient / 2, cyClient / 2, NULL) ; SetViewportOrgEx的参数总是使用装置单位。现在,逻辑点(0,0)将映射为装置点(cxClient/2,cyClient/2), 用下面的SetWindowOrgEx叙述可以获得与上面使用SetViewportOrgEx同样的效果: SetWindowOrgEx (hdc, -cxClient / 2, -cyClient / 2, NULL) ; 28,您可以使用下面两个函式取得目前视埠和视窗的原点: GetViewportOrgEx (hdc, &pt) ; GetWindowOrgEx (hdc, &pt) ; 其中pt是POINT结构。由GetViewportOrgEx传回的值是装置座标,而由GetWindowOrgEx传回的值是逻辑座标。 29,ract有四个成员left、top、right和bottom 可以通过呼叫下面的函数来方便的设置RECT的值 SetRect (&rect, xLeft, yTop, xRight, yBottom) ; 将矩形沿x轴和y轴移动几个单元: OffsetRect (&rect, x, y) ; 增减矩形的尺寸: InflateRect (&rect, x, y) ; 矩形各成员设定为0: SetRectEmpty (&rect) ; 将矩形复制给另一个矩形: CopyRect (&DestRect, &SrcRect) ; 取得两个矩形的交集: IntersectRect (&DestRect, &SrcRect1, &SrcRect2) ; 取得两个矩形的并集: UnionRect (&DestRect, &SrcRect1, &SrcRect2) ; 确定矩形是否为空: bEmpty = IsRectEmpty (&rect) ; 确定点是否在矩形内: bInRect = PtInRect (&rect, point) ; 30,PeekMessage (&msg, NULL, 0, 0, PM_REMOVE) ; 31,剪裁区域 hRgn = CreateRectRgn (xLeft, yTop, xRight, yBottom) ; 或 hRgn = CreateRectRgnIndirect (&rect) ; 也可以弄一个椭圆的剪裁区域 hRgn = CreateEllipticRgn (xLeft, yTop, xRight, yBottom) ; 或 hRgn = CreateEllipticRgnIndirect (&rect) ; 使用CreateRoundRectRgn建立圆角矩形剪裁区域 建立多边形剪裁区域 hRgn = CreatePolygonRgn (&point, iCount, iPolyFillMode) ; iRgnType = CombineRgn (hDestRgn, hSrcRgn1, hSrcRgn2, iCombine) ; 这一函式将两个剪裁区域(hSrcRgn1和hSrcRgn2)组合起来并用代号hDestRgn指向组合成的剪裁区域。这三个剪裁区域代号都必须是有效的, 32,通过GetUpdateRect可以知道失效举行的坐标 位图 1,创建位图的方法基本都会返回一个HBITMAP句柄,betmap和画笔画刷一样需要删除和选择 创建位图的第一个方法 HBITMAP CreateBitmap( int nWidth, int nHeight, UINT cPlanes, UINT cBitsPerPel, CONST VOID *lpvBits ); cPlanes:指明色彩平面数。 cBitsPerPel:指明每个像素的颜色用多少位来表示,它和上一个参数可以通过GetDeviceCaps函数用PLANES 和BITSPIXEL标识符来获得。 lpvBits:指向DDB像素位数组的指针,该数组的每行为偶数字节,记录位图像素的色彩信息。单色位图的每个像素仅需一位,这里不做详述。 第二种方法: HBITMAP CreateBitmapIndirect(CONST BITMAP *lpbm ); lpbm:指向BITMAP结构的指针,该结构记录了已创建的DDB位图的全部主要信息,它的域与CreateBitmap函数的参数对应,如下所示。 第三种 HBITMAP CreateCompatibleBitmap( HDC hdc, int nWidth, int nHeight ) ; hdc:不仅是指显示设备描述表,还可以是内存设备描述表,这在下一小节的实例程序screensnap中,将看到这个函数的用法。 nWidth:指位图的宽度。 nHeight:指位图的高度。 3,创建内存描述表很容易,只要根据某个实际设备的设备描述表句柄使用CreateCompatibleDC函数即可完成。例如: hdcMem = CreateCompatibleDC(hdc); 网站备案号: 京ICP备19050865号