win32汇编实现一个时钟

windows下的图像操作,涉及到图形的操作,我们就会想到GDI(图形设备接口),其实也就是一个大型的函数库,可以实现WINDOWS环境下的画线,画图,字体处理等操作。就如同这次分析的一个简单的时钟,我感觉可以分为如下几步:

资源文件的定义:

首先编写资源文件,这也是一个WIN32程序不可忽缺的一个环节(当然也可以不写,只不过丑陋了许多),这次资源文件只定义了一个图标文件,没有出现什么问题。

然后是:

GDI操作
1画点:时钟的刻度                     
画线:时钟的指针
3画图形:时钟的刻度
  
然后是窗口处理过程:

窗口操作
1         
与时钟有关的位置.坐标.半径.刻度的一系列计算。                   
                 
2
窗口过程:包括消息的处理等

3
注册窗口类:其中有一些自定义的窗口属性,

4
建立并显示窗口:指定窗口的一些

5消息循环:窗口的精华

关于GDI操作基本都是使用函数对设备环境对象进行操作,需要注意的就是一些API函数的参数以及返回值情况,在画线的时候(就是在画时钟指针的时候),使用LineTo()函数时第2.3个参数的坐标是时钟指针反向延长到圆心的那一小段线段与圆心相对的那一点的坐标,在使用_CalcX()和_CalcY()函数计算该点的坐标时,半径这个参数是根据自己的习惯设置的,比如例子程序中设置的是10(单位:像素),这个参数反映的是指针反向延长超出圆心那部分的长度,这个问题当时也是很纠结,看了好久才明白。

还有一点有意思的地方,就是例子程序在画时钟的时针的时候,这几句代码:

 .if     eax >=12
        sub   eax,12
       .endif
       mov     ecx,360/12
       mul     ecx
       movzx   ecx,@stTime.wMinute
       shr     ecx,1                                ;666666666666666666666666
       add     eax,ecx


这几句代码很简洁也很精辟,首先判断如果时间是采用的24小时制的则转换为12小时制的,下面计算时针在某时的角度,一个时钟面是360度,每小时所占的角度是30度,把当前的时间:分 的数值除以二(就是二进制的右移一位:shr  ecx,1),正好当前时间的“分”的数值除以2正好和每小时所占的30度成比例,时间“分”的数值除以二作为当前分针在某小时30度区域的位置,然后再加上这时计算出来的时针在整个时钟面所处的角度,就得到当前时针的具体位置,这个写的真心精辟简洁。

另一点就是计算点的坐标时,利用的浮点运算,以前没有接触,感觉很是陌生,但是经过仔细研究后,发现计算机进行数据计算的浮点运行确实很经典,与此相关我转载了一篇写的很经典,很清晰的文章介绍浮点运算,以便以后方便学习。

在计算时钟的半径,圆心坐标的时候也就是_CalcClockParam()函数的过程,

              

  .if     eax > ecx
               mov edx,ecx
               sub eax,ecx
               shr eax,1
               mov dwCenterX,0
               mov dwCenterY,eax
       .else   
               mov edx,eax
        sub ecx,eax
        shr ecx,1
        mov dwCenterX,ecx
        mov dwCenterY,0
       .endif
函数代码中dwCenterX 
或dwCenterY  得到的是时钟的边框距离当前窗口的距离,在后面的
shr     edx,1
       mov     dwRadius,edx
       add     dwCenterX,edx
       add     dwCenterY,edx

代码中,经过与半径相加才得到真正的圆心的坐标。这些都是写程序时很容易犯错误的地方。

最后一点注意的就是在创建窗口时( CreteWindowEx()函数),这个函数的4,5,6,7,这四个参数分别代表的的是创建的窗口左上角x坐标,左上角Y坐标,右下角X坐标,右下角Y坐标。再是这里说这个,是因为以前我记得这四个坐标代表的是:窗口左上角x坐标,左上角Y坐标,窗口宽度,窗口高度。这个窗口宽度与高度是要经过左上角的坐标与右下角的坐标计算出来的,而不是直接写出来的。这些都是在写程序的时候遇见的纠结过的问题。下面看一下程序源代码:

               

 .386
                .model flat,stdcall
                option casemap:none
                
include         windows.inc
include         gdi32.inc
includelib      gdi32.lib
include         user32.inc
includelib      user32.lib
include         kernel32.inc
includelib      kernel32.lib


IDI_ICON1       equ     101
ID_TIMER        equ     1
 
                .data?
hInstance       dd      ?
hWinMain        dd      ?
dwCenterX       dd      ?
dwCenterY       dd      ?
dwRadius        dd      ?


                .const
szClassName     db      'Clock',0
_dwPara180      dw      180
                .code


_CalcClockParam proc

       LOCAL   @stRect:RECT
       invoke  GetClientRect,hWinMain,addr @stRect
       mov     eax,@stRect.right
       sub     eax,@stRect.left            ;宽度
       mov     ecx,@stRect.bottom
       sub     ecx,@stRect.top            ;高度
       .if     eax > ecx
               mov edx,ecx
               sub eax,ecx
               shr eax,1
               mov dwCenterX,0
               mov dwCenterY,eax
       .else   
               mov edx,eax
        sub ecx,eax
        shr ecx,1
        mov dwCenterX,ecx
        mov dwCenterY,0
       .endif
       shr     edx,1
       mov     dwRadius,edx
       add     dwCenterX,edx
       add     dwCenterY,edx
       ret
       
_CalcClockParam endp


_CalcX          proc    _dwDegree,_dwRadius


       LOCAL   @dwReturn
       
       fild    dwCenterX
       fild    _dwDegree
       fldpi   
       fmul
       fild    _dwPara180
       fdivp   st(1),st
       fsin
       fild    _dwRadius
       fmul    
       fadd
       fistp   @dwReturn
       mov     eax,@dwReturn
       ret
_CalcX          endp


_CalcY          proc    _dwDegree,_dwRadius


                LOCAL   @dwReturn
                
                fild    dwCenterY
                fild    _dwDegree
                fldpi
                fmul
                fild    _dwPara180
                fdivp   st(1),st
                fcos  
                fild    _dwRadius
                fmul
                fsubp   st(1),st
                fistp   @dwReturn
                mov     eax,@dwReturn
                ret
_CalcY          endp


_DrawDot        proc    _hDC,_dwDegreeInc,_dwRadius

       LOCAL   @dwNowDegree,@dwR
       LOCAL   @dwX,@dwY
       
       mov     @dwNowDegree,0
       mov     eax,dwRadius
       sub     eax,10
       mov     @dwR,eax
       .while  @dwNowDegree <= 360
               finit
               invoke _CalcX,@dwNowDegree,@dwR
               mov    @dwX,eax
               invoke _CalcY,@dwNowDegree,@dwR
               mov    @dwY,eax
              
               mov    eax,@dwX
               mov    ebx,eax
               mov    ecx,@dwY
               mov    edx,ecx
               sub    eax,_dwRadius
               add    ebx,_dwRadius
               sub    ecx,_dwRadius
               add    edx,_dwRadius
               invoke Ellipse,_hDC,eax,ecx,ebx,edx
               mov    eax,_dwDegreeInc
               add    @dwNowDegree,eax
       .endw
       ret


_DrawDot        endp


_DrawLine       proc    _hDC,_dwDegree,_dwRadiusAdjust

       LOCAL   @dwR
       LOCAL   @dwX1,@dwY1,@dwX2,@dwY2
       
       mov     eax,dwRadius
       sub     eax,_dwRadiusAdjust
       mov     @dwR,eax
       invoke  _CalcX,_dwDegree,@dwR
       mov     @dwX1,eax
       invoke  _CalcY,_dwDegree,@dwR
       mov     @dwY1,eax
       add     _dwDegree,180
       invoke  _CalcX,_dwDegree,10           ;此处需注意     注意参数10
       mov     @dwX2,eax
       invoke  _CalcY,_dwDegree,10
       mov     @dwY2,eax
       invoke  MoveToEx,_hDC,@dwX1,@dwY1,NULL
       invoke  LineTo,_hDC,@dwX2,@dwY2
       ret


_DrawLine       endp


_ShowTime       proc    _hWnd,_hDC

       LOCAL   @stTime:SYSTEMTIME
       
       pushad
       invoke  GetLocalTime,addr @stTime
       invoke  _CalcClockParam
       invoke  GetStockObject,BLACK_BRUSH
       invoke  SelectObject,_hDC,eax
       invoke  _DrawDot,_hDC,360/12,3
       invoke  _DrawDot,_hDC,360/60,1
       invoke  CreatePen,PS_SOLID,1,0
       invoke  SelectObject,_hDC,eax
       invoke  DeleteObject,eax
       movzx   eax,@stTime.wSecond
       mov     ecx,360/60
       mul     ecx
       invoke  _DrawLine,_hDC,eax,15
       invoke  CreatePen,PS_SOLID,2,0
       invoke  SelectObject,_hDC,eax
       invoke  DeleteObject,eax
       movzx   eax,@stTime.wMinute
       mov     ecx,360/60
       mul     ecx
       invoke  _DrawLine,_hDC,eax,20
       invoke  CreatePen,PS_SOLID,3,0
       invoke  SelectObject,_hDC,eax
       invoke  DeleteObject,eax
       movzx   eax,@stTime.wHour
       .if     eax >=12
        sub   eax,12
       .endif
       mov     ecx,360/12
       mul     ecx
       movzx   ecx,@stTime.wMinute
       shr     ecx,1                                ;666666666666666666666666
       add     eax,ecx
       invoke  _DrawLine,_hDC,eax,30
       ret


_ShowTime       endp


_ProcWinMain    proc    uses ebx edi esi hWnd,uMsg,wParam,lParam
                LOCAL   @stPS:PAINTSTRUCT
                
                mov     eax,uMsg
                .if     eax == WM_TIMER
                invoke InvalidateRect,hWnd,NULL,TRUE
                .elseif eax == WM_PAINT
                invoke BeginPaint,hWnd,addr @stPS
                invoke _ShowTime,hWnd,eax
                invoke EndPaint,hWnd,addr @stPS
                .elseif eax == WM_CREATE
                        invoke SetTimer,hWnd,ID_TIMER,1000,NULL
                .elseif eax == WM_CLOSE
                invoke KillTimer,hWnd,ID_TIMER
                invoke DestroyWindow,hWinMain
                invoke PostQuitMessage,NULL
                .else   
                        invoke DefWindowProc,hWnd,uMsg,wParam,lParam
                ret
                .endif
                xor     eax,eax
                ret
_ProcWinMain    endp


_WinMain        proc    

       LOCAL   @stWndClass:WNDCLASSEX
       LOCAL   @stMsg:MSG
       
       invoke  GetModuleHandle,NULL
       mov     hInstance,eax
       invoke  RtlZeroMemory,addr @stWndClass,sizeof @stWndClass
       invoke  LoadIcon,hInstance,IDI_ICON1
       mov     @stWndClass.hIcon,eax
       mov     @stWndClass.hIconSm,eax
       invoke  LoadCursor,0,IDC_ARROW
       mov     @stWndClass.hCursor,eax
       push    hInstance
       pop     @stWndClass.hInstance
       mov     @stWndClass.cbSize,sizeof WNDCLASSEX
       mov     @stWndClass.style,CS_HREDRAW or CS_VREDRAW
       mov     @stWndClass.lpfnWndProc,offset _ProcWinMain
       mov     @stWndClass.hbrBackground,COLOR_WINDOW + 1
       mov     @stWndClass.lpszClassName,offset szClassName
       invoke  RegisterClassEx,addr @stWndClass
       invoke  CreateWindowEx,WS_EX_CLIENTEDGE,offset szClassName,offset szClassName,\
               WS_OVERLAPPEDWINDOW,100,100,250,270,NULL,NULL,hInstance,NULL
       mov     hWinMain,eax
       invoke  ShowWindow,hWinMain,SW_SHOWNORMAL
       invoke  UpdateWindow,hWinMain
       .while  TRUE
        invoke  GetMessage,addr @stMsg,NULL,0,0
        .break  .if eax ==0
        invoke  TranslateMessage,addr @stMsg
        invoke  DispatchMessage,addr @stMsg 
       .endw
       ret
_WinMain        endp


start:
                call    _WinMain
                invoke  ExitProcess,NULL
                end     start


上面就是源代码,下面介绍一下,遇见的一些陌生的API函数:


BitBlt()  (这个函数没有出现在上面程序中,因为属于GDI的常用函数才列出来)
功能:该函数对指定的源设备环境区域中的像素进行位块(bit_block)转换,以传送到目标设备环境。
原型:
BOOL BitBlt(HDC hdcDest,int nXDest,int nYDest,int nWidth,int nHeight,HDC hdcSrc,int nXSrc,int nYSrc,DWORD dwRop)
参数:
hdcDest:指向目标设备环境的句柄。

nXDest:指定目标矩形区域左上角的X轴逻辑坐标。

nYDest:指定目标矩形区域左上角的Y轴逻辑坐标。

nWidth:指定源和目标矩形区域的逻辑宽度。

nHeight:指定源和目标矩形区域的逻辑高度。

hdcSrc:指向源设备环境的句柄。

nXSrc:指定源矩形区域左上角的X轴逻辑坐标。

nYSrc:指定源矩形区域左上角的Y轴逻辑坐标。

dwRop:指定光栅操作代码。这些代码将定义源矩形区域的颜色数据,如何与目标矩形区域的颜色数据组合以完成最后的颜色。

下面列出了一些常见的光栅操作代码:

BLACKNESS:表示使用与物理调色板的索引0相关的色彩来填充目标矩形区域,(对缺省的物理调色板而言,该颜色为黑色)。

DSTINVERT:表示使目标矩形区域颜色取反。

MERGECOPY:表示使用布尔型的AND(与)操作符将源矩形区域的颜色与特定模式组合一起。

MERGEPAINT:通过使用布尔型的OR(或)操作符将反向的源矩形区域的颜色与目标矩形区域的颜色合并。

NOTSRCCOPY:将源矩形区域颜色取反,于拷贝到目标矩形区域。

NOTSRCERASE:使用布尔类型的OR(或)操作符组合源和目标矩形区域的颜色值,然后将合成的颜色取反。

PATCOPY:将特定的模式拷贝到目标位图上。

PATPAINT:通过使用布尔OR(或)操作符将源矩形区域取反后的颜色值与特定模式的颜色合并。然后使用OR(或)操作符将该操作的结果与目标矩形区域内的颜色合并。

PATINVERT:通过使用XOR(异或)操作符将源和目标矩形区域内的颜色合并。

SRCAND:通过使用AND(与)操作符来将源和目标矩形区域内的颜色合并。

SRCCOPY:将源矩形区域直接拷贝到目标矩形区域。

SRCERASE:通过使用AND(与)操作符将目标矩形区域颜色取反后与源矩形区域的颜色值合并。

SRCINVERT:通过使用布尔型的XOR(异或)操作符将源和目标矩形区域的颜色合并。

SRCPAINT:通过使用布尔型的OR(或)操作符将源和目标矩形区域的颜色合并。

WHITENESS:使用与物理调色板中索引1有关的颜色填充目标矩形区域。(对于缺省物理调色板来说,这个颜色就是白色)

返回值:

如果函数成功,那么返回值非零;如果函数失败,则返回值为零



GetDC()

功能:

该函数检索一指定窗口的客户区域或整个屏幕的显示设备上下文环境的句柄,以后可以在GDI函数中使用该句柄来在设备上下文环境中绘图。 GetDCEx函数是GetDC的一个扩展,它能使应用程序更多地控制在客户区域内如何或是否发生剪切

原型:

HDC GetDC(HWND hWnd);

参数:

hWnd:设备上下文环境被检索的窗口的句柄,如果该值为NULL,GetDC则检索整个屏幕的设备上下文环境。

返回值:

如果成功,返回指定窗口客户区的设备上下文环境;如果失败,返回值为Null。



ReleaseDC()

功能:

函数释放设备上下文环境(DC)供其他应用程序使用。函数的效果与设备上下文环境类型有关。它只释放公用的和设备上下文环境,对于类或私有的则无效。

原型;

int ReleaseDC(HWND hWnd, HDC hdc);

参数:


hWnd:指向要释放的设备上下文环境所在的窗口的句柄。

hDC:指向要释放的设备上下文环境的句柄。

返回值;

返回值说明了设备上下文环境是否释放;如果释放成功,则返回值为1;如果没有释放成功,则返回值为0。



MoveToEx()

功能:

本函数将当前绘图位置移动到某个具体的点,同时也可获得之前位置的坐标

原型:

WINGDIAPI BOOL WINAPI MoveToEx(

HDC hdc,

int X,

int Y,

LPPOINT lpPoint

);

参数:
HDC hdc:传入参数,设备上下文句柄。

int X:传入参数:新位置的X坐标。

int Y:传入参数:新位置的Y坐标。

LPPOINT lpPoint:传出参数:一个指向POINT结构的指针,用来存放上一个点的位置,若此参数为NULL,则不保存上一个点的位置

返回值:
返回TRUE代表移动成功,FALSE代表失败



LineTo()

功能:

用当前画笔画一条线,从当前位置(这个函数和MoveTo()函数配合使用)连到一个指定的点。这个函数调用完毕,当前位置变成x,y

原型:

WINGDIAPI BOOL WINAPI LineTo(

HDChdc,

intX,

intY,

);


参数:

hdc:设备场景句柄

X:线段终点X坐标位置,采用逻辑坐标表示。这个点不会实际画出来;它不属于线段的一部份

Y:线段终点Y坐标位置,采用逻辑坐标表示。这个点不会实际画出来;它不属于线段的一部份

返回值:
返回TRUE代表移动成功,FALSE代表失败



GetLocalTime()

功能:

用来获取当地的当前系统日期和时间
原型:

VOID GetLocalTime(

LPSYSTEMTIME lpSystemTime //address of system times structure

);

参数:
lpSystemTime: 指向一个用户自定义包含日期和时间信息的类型为 SYSTEMTIME 的变量,该变量用来保存函数获取的时间信息。

此函数会把获取的系统时间信息存储到SYSTEMTIME结构体里边

typedef struct _SYSTEMTIME

{

WORD wYear;//年

WORD wMonth;//月

WORD wDayOfWeek;//星期,0为星期日,1为星期一,2为星期二……

WORD wDay;//日

WORD wHour;//时

WORD wMinute;//分

WORD wSecond;//秒

WORD wMilliseconds;//毫秒

}SYSTEMTIME,*PSYSTEMTIME

返回值:

把获取的日期时间存放到指定的SYSTEMTIME结构中去。



GetStockObject()

功能:

该函式检索预定义的备用笔、刷子、字体或者调色板的句柄。

原型:

HGDIOBJ GetStockObject(int fnObject);

参数:

fnObject:指定对象的类型,该参数可取如下值之一;

BLACK_BRUSH:黑色画刷;DKGRAY_BRUSH:暗灰色画刷;

DC_BRUSH:在Windows98,Windows NT 5.0和以后版本中为纯颜色画刷,缺省色为白色,可以用SetDCBrushColor函数改变颜色,更多的信息参见以下的注释部分。

GRAY_BRUSH:灰色画刷笔;HOLLOW_BRUSH:空画刷(相当于NULL_BRUSH);

LTGRAY_BRUSH:亮灰色画刷;NULL_BRUSH:空画刷(相当于HOLLOW_BRUSH);

WHITE_BRUSH:白色画刷;

BLACK_PEN:黑色钢笔;

DC_PEN:在Windows98、Windows NT 5.0和以后版本中为纯色钢笔,缺省色为白色,使用SetDCPenColor函数可以改变色彩,更多的信息,参见下面的注释部分。

WHITE_PEN:白色钢笔;

ANSI_FIXED_FONT:在Windows中为固定间距(等宽)系统字体;

ANSI_VAR_FONT:在Windows中为变间距(比例间距)系统字体;

DEVICE_DEFAUCT_FONT:在WindowsNT中为设备相关字体;

DEFAULT_GUI_FONT:用户界面对象缺省字体,如菜单和对话框;

OEM_FIXED_FONT:原始设备制造商(OEM)相关固定间距(等宽)字体;

SYSTEM_FONT:系统字体,在缺省情况下,系统使用系统字体绘制菜单,对话框控制和文本;

SYSTEM_FIXED_FONT:固定间距(等宽)系统字体,该对象仅提供给兼容16位Windows版本;

DEFAULT_PALETTE:缺省调色板,该调色板由系统调色板中的静态色彩组成。

返回值:
如果成功,返回值标识申请的逻辑对象,如果失败,返回值为NULL。



SelectObject()

功能:

该函数选择一对象到指定的设备上下文环境中,该新对象替换先前的相同类型的对象。

原型:

HGDIOBJ SelectObject(HDC hdc, HGDIOBJ hgdiobj)

参数:

hdc:设备上下文环境的句柄。

hgdiobj:被选择的对象的句柄,该指定对象必须由如下的函数创建。

位图:CreateBitmap, CreateBitmapIndirect, CreateCompatible Bitmap, CreateDIBitmap, CreateDIBsection(只有内存设备上下文环境可选择位图,并且在同一时刻只能一个设备上下文环境选择位图)。

画刷:CreateBrushIndirect, CreateDIBPatternBrush, CreateDIBPatternBrushPt, CreateHatchBrush, CreatePatternBrush, CreateSolidBrush。

字体:CreateFont, CreateFontIndirect。

笔:CreatePen, CreatePenIndirect。

区域:CombineRgn, CreateEllipticRgn, CreateEllipticRgnIndirect, CreatePolygonRgn, CreateRectRgn,CreateRectRgnIndirect。

返回值:
如果选择对象不是区域并且函数执行成功,那么返回值是被取代的对象的句柄;如果选择对象是区域并且函数执行成功,返回如下一值:

SIMPLEREGION:区域由单个矩形组成;

COMPLEXREGION:区域由多个矩形组成;

NULLREGION:区域为空。

如果发生错误并且选择对象不是一个区域,那么返回值为NULL,否则返回HGDI_ERROR。



CreatePen()

功能:

用指定的样式、宽度和颜色创建一个画笔

原型:

HPEN CreatePen(int nPenStyle, int nWidth, COLORREF crColor);

参数:

nPenStyle ------ Long,指定画笔样式,可以是下述常数之一

PS_SOLID                 ​画笔画出的是实线

PS_DASH                  ​画笔画出的是虚线(nWidth必须不大于1)

PS_DOT                    ​画笔画出的是点线(nWidth必须不大于1)

PS_DASHDOT    ​       画笔画出的是点划线(nWidth必须不大于1)

PS_DASHDOTDOT    ​画笔画出的是点-点-划线(nWidth必须不大于1)

PS_NULL                    ​画笔不能画图

PS_INSIDEFRAME    ​由椭圆、矩形、圆角矩形、饼图以及弦等生成的封闭对象框时,画线宽度向内扩展。

如指定的准确RGB颜 色不存在,就进行抖动处理

nWidth --------- Long,以逻辑单位表示的画笔的宽度

crColor -------- Long,画笔的RGB颜色

返回值:
如函数执行成功,就返回指向新画笔的一个句柄;否则返回零


DeleteObject()

功能:

该函数删除一个逻辑笔、画笔、字体、位图、区域或者调色板,释放所有与该对象有关的系统资源,在对象被删除之后,指定的句柄也就失效了。

原型:

BOOL DeleteObject(HGDIOBJ hObject)

参数:

hObject:逻辑笔、画笔、字体、位图、区域或者调色板的句柄。

返回值:

成功,返回非零值;如果指定的句柄无效或者它已被选入设备上下文环境,则返回值为零



ExtCreatePen()

功能:

创建一个扩展画笔(装饰或几何)

原型:

ExtCreatPen (

dwPenStyle , // 画笔样式

dwWidth , // 指定线宽

lplb , // 逻辑画刷变量

dwStyleCout , // 如指定了PS_USERSTYLE,则代表lpStyle数组中的条目数量

lpStyle // 指定PS_USERSTYLE的"线段/空白"对

)

参数:
dwPenStyle (Long)

画笔样式来自下述常数组的任何一个常数的组合(OR运算):

PS_COSMETIC or PS_GEOMETRIC
画笔的类型
PS_ALTERNATE, PS_SOLID, PS_DASH, PS_DOT, PS_DASHDOT, PS_DASHDOTDOT, PS_NULL, PS_USERSTYLE, PS_INSIDEFRAME
画笔的样式
PS_ENDCAP_???
画笔的笔尖
PS_JOIN_???
在图形中连接线段或在路径中连接直线的方式
dwWidth (Long)

指定线宽。几何画笔的线宽肯定是1。

lplb

LOGBRUSH,lbColor代表画笔颜色。对于装饰画笔,lbStyle为PS_SOLID;对于几何画笔,lbStyle则代表实际的样式。针对几何画笔,必须设置其他所有字体。

dwStyleCount (Long)

如指定了PS_USERSTYLE,则代表lpStyle数组中的条目数量。

lpStyle (Long)

指定PS_USERSTYLE的"线段/空白"对(原文:Line/space pairs for PS_USERSTYLE)

返回值:

如执行成功,返回一个指向扩展画笔的句柄。零表示执行出错。一旦不再需要,记得用DeleteObject将画笔删除。



CreatePenIndirect()

功能:

根据指定的LOGPEN结构创建,参数表:lpLogPen ------- LOGPEN,逻辑画笔结构。这个结构与CreatePen函数的参数非常接近。

原型:

HPEN CreatePenIndirect( _In_ const LOGPEN *lplgpn);

参数:

lpLogPen ------- LOGPEN,逻辑画笔结构

返回值:

如执行成功,返回指向新画笔的一个句柄;否则返回零



CreateSolidBrush()

功能:


该函数创建一个具有指定颜色的逻辑刷子。

初始化一个指定颜色的画刷。画笔可以随后被选为任何设备上下文的当前刷子。

参数原型:

HBRUSH CreateSolidBrush(DWORD COLOR)

返回值:

如果该函数执行成功,那么返回值标识一个逻辑实心刷子;如果函数失败,那么返回值为NULL



CreateHatchBrush()

功能:

该函数可以创建一个具有指定阴影模式和颜色的逻辑刷子。

原型:

HBRUSH CreateHatchBrush(int fnStyle, COLORREF clrref);

参数:

fnStyle:指定刷子的阴影样式。该参数可以取下列值,这些值的含义为:

HS_BDIAGONAL:表示45度向上,从左至右的阴影(/);

HS_CROSS:水平和垂直交叉阴影(+++++);

HS_DIAGCROSS:45度交叉阴影(XXXXX);

HS_FDIAGONAL:45度向下,自左至右阴影(\\\\\\);

HS_HORIZONTAL:水平阴影(-----);

HS_VERTICAL:垂直阴影(|||||)。

cirref:指定用于阴影的刷子的前景色。

返回值:
如果函数执行成功,那么返回值标识为逻辑刷子;如果函数执行失败,那么返回值为NULL。



CreatePatternBrush()

功能:

创建具有指定位图模式的逻辑刷子,该位图不能是DIB类型的位图,DIB位图是由CreateDIBSection函数创建的

原型:

HBRUSH CreatePatternBrush()

返回值:

如果该函数执行成功,那么返回值标识为一个逻辑刷子,如果该函数执行失败,那么返回值为NULL



CreateBrushIndirect()

功能:

可以创建具有指定风格、颜色和模式的逻辑刷子

原型:

HBRUSH CreateBrushlndirect(CONST LOGBRUSH *lplb);

参数:

lplb:指向LOGBRUSH结构的指针,该结构包含与刷子有关的信息。

返回值:

如果函数执行成功,那么返回值标识一个逻辑刷子;如果函数执行失败,则返回值为NULL



SetPixel()

功能:

将指定坐标处的像素设为指定的颜色。

原型:

COLORREF SetPixel(HDC hdc, int X, int Y, COLORREF crColor);

参数:

hdc:设备环境句柄。

X:指定要设置的点的X轴坐标,按逻辑单位表示坐标。

Y:指定要设置的点的X轴坐标,按逻辑单位表示坐标。

crColor::指定要用来绘制该点的颜色

返回值:


如果函数执行成功,那么返回值就是函数设置像素的RGB颜色值。这个值可能与crColor指定的颜色有所不同,

之所以有时发生这种情况是因为没有找到对指定颜色进行真正匹配造成的。

如果函数失败,那么返回值是-1。



GetPixel()

功能:

该函数检索指定坐标点的像素的RGB颜色值。

原型:

COLORREF GetPixel(HDC hdc, int nXPos, int nYPos)

参数:

hdc:设备环境句柄。

nXPos:指定要检查的像素点的逻辑X轴坐标。

nYPos:指定要检查的像素点的逻辑Y轴坐标。

返回值:

返回值是该象像点的RGB值。如果指定的像素点在当前剪辑区之外;那么返回值是CLR_INVALID。



GetCurrentPositionEX()

功能:

该函数获取逻辑坐标中的当前位置

原型:
BOOL GetCurrentPositionEx(HDC hdc, LPPOINT lpPoint);

参数:

hdc:指向设备环境的句柄。
lpPoint:指向接收当前位置坐标的POINT结构的指针。

返回值:

如果函数调用成功,返回值为非零值,否则为零



InvaliddateRect()

功能:

该函数向指定的窗体更新区域添加一个矩形,然后窗口客户区域的这一部分将被重新绘制

原型:


BOOL InvalidateRect(

HWND hWnd, // handle of window with changed update region

CONST RECT *lpRect, // address of rectangle coordinates

BOOL bErase // erase-background flag

);


参数:


hWnd:要更新的客户区所在的窗体的句柄。如果为NULL,则系统将在函数返回前重新绘制所有的窗口, 然后发送 WM_ERASEBKGND 和 WM_NCPAINT 给窗口过程处理函数。

lpRect:无效区域的矩形代表,它是一个结构体指针,存放着矩形的大小。如果为NULL,全部的窗口客户区域将被增加到更新区域中。

bErase:指出无效矩形被标记为有效后,是否重画该区域,重画时用预先定义好的画刷。当指定TRUE时需要重画。

返回值:

函数成功则返回非零值,否则返回零值。

说明:被标记为无效矩形的区域直到WM_PAINT消息被处理完之后才会消失,或者使用ValidateRect(),ValidateRgn()函数来使之有效。当应用程序的消息队列中为空时,并且窗体要更新的区域非空时,系统会发送一个WM_PAINT消息到窗体。

这两个都用于声明客户区无效,当下一个WM_PAINT消息到来时发生重画。

其中InvalidateRect(hwnd, NULL, true);重画时将擦除背景。

InvalidateRect(hwnd, NULL, false);重画时不擦除背景















 










 



  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值