WIN32汇编语言中位图的使用

说到位图。我们事实上非常早就接触过。从最早接触计算机,我们应该就知道有图片这个东西,然后再进一步说,图片在电脑上有好几种格式比方jpg. gif .png.pcx.bmp等等,当中bmp格式的图片文件事实上就是位图(windows的说法是DIB),位图文件也分为几种(由于存储的位置不同)。由于在学的是罗云斌老师的书籍,这次依然还拿他老人家的程序学习,拓展创新,学为己用。毕竟还不是老手。一步一步走才干够。

了解了位图是什么东西。以下总结一下制作一个能显示位图的时钟的大体流程:

资源脚本文件
 1.创建资源project                           20.c                      
2.加入资源 位图。图标,光标
3.编译资源脚本 生成20.resc文件


                    GDI操作
1.画线    时钟指针                       
2.绘图 钟面,背景,边框。椭圆小点


窗体操作
1.与时钟有关的计算 半径,圆心。刻度位置等
2.时钟的初始化 设置时钟刚出来时的状态等
3.窗体过程 对于不同的消息的处理操作
4.注冊窗体类 主要是一些自己定义的窗体属性
5.创建并显示窗体 主要包含窗体的显示状态等
6.消息循环 窗体核心


上面整体给这个程序来了一个描写叙述,以下来具体介绍一下,以及记录一下学习的时候遇见的一些问题和自己的一些心得体会。

首先我们来创建资源文件,相同我依然是用的ResEdit,经经常使用了,已经习惯了,看个人口味了。这个无所谓。都是一样的,这次由于不须要使用通常所用的显式的菜单以及对话框,子控件等资源,因此看起来资源脚本的代码量非常好少,仅仅需加入创建好的位图文件。图标文件,光标文件就可以我写的资源码例如以下:

// Generated by ResEdit 1.6.6
// Copyright (C) 2006-2015
// http://www.resedit.net
#include <windows.h>
#include <commctrl.h>
#include <richedit.h>
#define IDB_CIRCLE2                             115
#define IDB_BACK1                               120
#define IDB_BACK2                               117
#define IDB_CIRCLE1                             118
#define IDB_MASK1                               119
#define IDB_MASK2                               116
#define ICO_MAIN                                121
#define IDC_MOVE                                122
#define IDC_MAIN                                123
//
// Bitmap resources
//
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
IDB_BACK1          BITMAP         ".\\Back1.bmp"
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
IDB_BACK2          BITMAP         ".\\Back2.bmp"
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
IDB_CIRCLE1        BITMAP         ".\\Circle1.bmp"
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
IDB_CIRCLE2        BITMAP         ".\\Circle2.bmp"
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
IDB_MASK1          BITMAP         ".\\Mask1.bmp"
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
IDB_MASK2          BITMAP         ".\\Mask2.bmp"
//
// Cursor resources
//
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
IDC_MOVE           CURSOR         ".\\Move.cur"
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
IDC_MAIN           CURSOR         ".\\Main.cur"
//
// Icon resources
//
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
ICO_MAIN           ICON           ".\\Main.ico"



关于资源文件有一点须要注意。就是在编写资源脚本文件的时候当你加入某个资源项的时候,都会相应有一个相应的ID值,就像是子控件的控件ID一样,尽管在编译资源是右边的选项栏里面没有显示,可是,当你把资源文件写完的时候,在ResEdit安装目录下含自己创建的project名字的目录在该目录下有关于资源中用到的文件,当中有一个resource.h的.h文件,我们能够以文档的形式打开,发现当中是一些定义好宏定义。生明了某个资源名字相应的INT型数值,对于这个数值,一般的程序来说其先后顺序,以及数值的大小都没有什么严格的要求,可是本次程序,当你在敲代码实现代码的时候就会发现,有4个位图资源的ID数值是有特殊要求的,例如以下

#define IDB_CIRCLE2                             115
#define IDB_MASK2                               116
#define IDB_CIRCLE1                             118
#define IDB_MASK1                               119


你假设整体去看资源文件的话或许不会发现什么可是把这四个单拉出来你就会发现,IDB_CIRCLE2 与IDB_MASK2       的定义的INT型数值ID分别为115,116。    115+1=116.     

然后看 IDB_CIRCLE1 与IDB_MASK1 的INT型数值ID分别为  118,119。   118+1=119,也就是说IDM_CIRCLE(1,2)+1=IDM_MASK(1,2)(通俗的说), 为什么要这样呢(事实上我在执行完程序之后才明确的,,刚開始也不知道当中的用意),以下来看一下20.asm中的一段相关代码:

_CreateBackGround    proc

            LOCAL @hDc,@hDcCircle,@hDcMask
            LOCAL @hBmpBack,@hBmpCircle,@hBmpMask
       invoke    GetDC,hWinMain
       mov       @hDc,eax
       invoke    CreateCompatibleDC,@hDc
       mov       hDcBack,eax
       invoke    CreateCompatibleDC,@hDc
       mov       hDcClock,eax
       invoke    CreateCompatibleDC,@hDc
       mov       @hDcCircle,eax
       invoke    CreateCompatibleDC,@hDc
       mov       @hDcMask,eax
       invoke    CreateCompatibleBitmap,@hDc,CLOCK_SIZE,CLOCK_SIZE
       mov       hBmpBack,eax
       invoke    CreateCompatibleBitmap,@hDc,CLOCK_SIZE,CLOCK_SIZE
       mov       hBmpClock,eax
       invoke    ReleaseDC,hWinMain,@hDc
       invoke    LoadBitmap,hInstance,dwNowBack
       mov       @hBmpBack,eax
       invoke    LoadBitmap,hInstance,dwNowCircle
       mov       @hBmpCircle,eax
       mov       eax,dwNowCircle
       inc       eax                                                  ;注意此处
       invoke    LoadBitmap,hInstance,eax
       mov       @hBmpMask,eax
如上面代码是_CreateBackGround 子函数的一部分,在标有凝视的地方,有一句 代码:
mov       eax,dwNowCircle
        inc       eax     
dwNowCircle是一个全局变量。在_ProcWinMain 子函数中处理COMMAND消息的时候有这种几句代码:
.elseif eax == WM_COMMAND
mov eax,wParam
.if ax ==IDM_BACK1
mov dwNowBack,IDB_BACK1                         。注意dwNowBack的值
invoke CheckMenuRadioItem,hMenu,IDM_BACK1,IDM_BACK2,IDM_BACK1,NULL
.elseif ax == IDM_BACK2
mov dwNowBack,IDB_BACK2                          ;注意dwNowBack的值
invoke CheckMenuRadioItem,hMenu,IDM_BACK1,IDM_BACK2,IDM_BACK2,NULL
.elseif ax == IDM_CIRCLE1
mov dwNowCircle,IDB_CIRCLE1                      ;注意dwNowCircle的值
invoke CheckMenuRadioItem,hMenu,IDM_CIRCLE1,IDM_CIRCLE2,IDM_CIRCLE1,NULL
.elseif ax == IDM_CIRCLE2
mov dwNowCircle,IDB_CIRCLE2                       ;注意dwNowCircle的值
invoke CheckMenuRadioItem,hMenu,IDM_CIRCLE1,IDM_CIRCLE2,IDM_CIRCLE2,NULL
.elseif ax == IDM_EXIT
call _Quit
xor eax,eax
ret
.endif
invoke _DeleteBackGround
invoke _CreateBackGround                                              已经对dwNowBack或者dwNowCircle赋值。然后调用子函数。
invoke _CreateClockPic


注意上面标有凝视的地方。意思就是当收到COMMAND消息的时候。假设消息内容是按下某个选项触发的。那么就把这个选项的ID值赋值给全局变量dwNowBack或者dwNowCircle。假如说当这个选项是IDM_CIRCLE1或者IDM_CIRCLE2的时候。dwNowCircle的值就是118或115,此时再看_CreateBackGround子函数中作凝视的代码,就会发现“inc dwNowCircle”  之后dwNowCircle的值就变为对应的119或者116 ,此时你再对比程序开头声明的等值或者资源文件的宏定义,会发现,IDB_MASK1与IDB_MASK2的int型ID数值为  119与116,也就是说经过“inc dwNowCircle” 这句代码之后,dwNowCircle的值就是IDB_MASK1或者IDB_MASK2的值,代表的就是遮掩图片的ID。

关于这个问题刚開始我也是非常纠结,后来才明确(对于这个方式我感觉还是非常陌生的,我感觉倒不如用MOV指令。毕竟我是新手。预计那样会开销比較大,)。

以下来详细看一下程序代码:


.386
.model flat, stdcall
option casemap :none

include windows.inc
include user32.inc
includelib user32.lib
include kernel32.inc
includelib kernel32.lib
include Gdi32.inc
includelib Gdi32.lib


CLOCK_SIZE equ150
ICO_MAIN equ 121              
IDC_MAIN equ 123
IDC_MOVE equ 122
IDB_BACK1 equ 120
IDB_CIRCLE1 equ118     ;;注意Circle1的ID值必须是加一后等于MASK1的ID值,不然不会成功。
IDB_MASK1 equ 119
IDB_BACK2 equ 117
IDB_CIRCLE2 equ115      ;注意Circle2的ID值必须是加一后等于MASK2的ID值,不然不会成功。
IDB_MASK2 equ 116              
ID_TIMER equ 1
IDM_BACK1 equ 100
IDM_BACK2 equ 101
IDM_CIRCLE1 equ102
IDM_CIRCLE2 equ103
IDM_EXIT equ 104


.data?

hInstance dd ?

hWinMain dd ? hCursorMove dd?;Cursor when move hCursorMain dd?;Cursor when normal hMenu dd ? hBmpBack dd ?

hDcBack dd ? hBmpClock dd ? hDcClock dd ?

dwNowBack dd ?

dwNowCircle dd?

.const szClassName db'Clock',0 dwPara180 dw 180 dwRadius dw CLOCK_SIZE/2 szMenuBack1 db'使用格子背景(&A)',0 szMenuBack2 db'使用花布背景(&B)',0 szMenuCircle1 db'使用淡蓝色边框(&C)',0 szMenuCircle2 db'使用粉红色边框(&D)',0 szMenuExit db '退出(&X)...',0 .code _CalcX proc _dwDegree,_dwRadius LOCAL @dwReturn fild dwRadius fild _dwDegree fldpi fmul ;角度*Pi fild dwPara180 fdivp st(1),st;角度*Pi/180 fsin ;Sin(角度*Pi/180) fild _dwRadius fmul ;半径*Sin(角度*Pi/180) fadd ;X+半径*Sin(角度*Pi/180) fistp @dwReturn mov eax,@dwReturn ret _CalcX endp _CalcY proc _dwDegree,_dwRadius LOCAL @dwReturn fild dwRadius 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 _DrawLine proc_hDC,_dwDegree,_dwRadius LOCAL @dwX1,@dwY1,@dwX2,@dwY2 invoke _CalcX,_dwDegree,_dwRadius mov @dwX1,eax invoke _CalcY,_dwDegree,_dwRadius mov @dwY1,eax add _dwDegree,180 invoke _CalcX,_dwDegree,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 _CreateClockPic proc LOCAL @stTime:SYSTEMTIME pushad invoke BitBlt,hDcClock,0,0,CLOCK_SIZE,CLOCK_SIZE,hDcBack,0,0,SRCCOPY invoke GetLocalTime,addr @stTime invoke CreatePen,PS_SOLID,1,0 invoke SelectObject,hDcClock,eax invoke DeleteObject,eax movzx eax,@stTime.wSecond mov ecx,360/60 mul ecx;秒针度数 = 秒 * 360/60 invoke _DrawLine,hDcClock,eax,60 invoke CreatePen,PS_SOLID,2,0 invoke SelectObject,hDcClock,eax invoke DeleteObject,eax movzx eax,@stTime.wMinute mov ecx,360/60 mul ecx;分针度数 = 分 * 360/60 invoke _DrawLine,hDcClock,eax,55 invoke CreatePen,PS_SOLID,3,0 invoke SelectObject,hDcClock,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 add eax,ecx invoke _DrawLine,hDcClock,eax,50 invoke GetStockObject,NULL_PEN invoke SelectObject,hDcClock,eax invoke DeleteObject,eax popad ret _CreateClockPic endp _CreateBackGround proc LOCAL @hDc,@hDcCircle,@hDcMask LOCAL @hBmpBack,@hBmpCircle,@hBmpMask invoke GetDC,hWinMain mov @hDc,eax invoke CreateCompatibleDC,@hDc mov hDcBack,eax invoke CreateCompatibleDC,@hDc mov hDcClock,eax invoke CreateCompatibleDC,@hDc mov @hDcCircle,eax invoke CreateCompatibleDC,@hDc mov @hDcMask,eax invoke CreateCompatibleBitmap,@hDc,CLOCK_SIZE,CLOCK_SIZE mov hBmpBack,eax invoke CreateCompatibleBitmap,@hDc,CLOCK_SIZE,CLOCK_SIZE mov hBmpClock,eax invoke ReleaseDC,hWinMain,@hDc invoke LoadBitmap,hInstance,dwNowBack mov @hBmpBack,eax invoke LoadBitmap,hInstance,dwNowCircle mov @hBmpCircle,eax mov eax,dwNowCircle inc eax invoke LoadBitmap,hInstance,eax mov @hBmpMask,eax invoke SelectObject,hDcBack,hBmpBack invoke SelectObject,hDcClock,hBmpClock invoke SelectObject,@hDcCircle,@hBmpCircle invoke SelectObject,@hDcMask,@hBmpMask invoke CreatePatternBrush,@hBmpBack ;格子背景 push eax invoke SelectObject,hDcBack,eax invoke PatBlt,hDcBack,0,0,CLOCK_SIZE,CLOCK_SIZE,PATCOPY invoke DeleteObject,eax invoke BitBlt,hDcBack,0,0,CLOCK_SIZE,CLOCK_SIZE,@hDcMask,0,0,SRCAND ;利用遮掩图片和ROP码画时钟边框(淡蓝色边框) invoke BitBlt,hDcBack,0,0,CLOCK_SIZE,CLOCK_SIZE,@hDcCircle,0,0,SRCPAINT invoke DeleteDC,@hDcCircle invoke DeleteDC,@hDcMask invoke DeleteObject,@hBmpBack invoke DeleteObject,@hBmpCircle invoke DeleteObject,@hBmpMask ret _CreateBackGround endp _DeleteBackGround proc invoke DeleteDC,hDcBack invoke DeleteDC,hDcClock invoke DeleteObject,hBmpBack invoke DeleteObject,hBmpClock ret _DeleteBackGround endp _Quit proc invoke KillTimer,hWinMain,ID_TIMER invoke DestroyWindow,hWinMain invoke PostQuitMessage,NULL invoke _DeleteBackGround invoke DestroyMenu,hMenu ret _Quit endp _Init proc LOCAL @hBmpBack,@hBmpCircle invoke CreatePopupMenu mov hMenu,eax invoke AppendMenu,hMenu,0,IDM_BACK1,offset szMenuBack1 invoke AppendMenu,hMenu,0,IDM_BACK2,offset szMenuBack2 invoke AppendMenu,hMenu,MF_SEPARATOR,0,NULL invoke AppendMenu,hMenu,0,IDM_CIRCLE1,offset szMenuCircle1 invoke AppendMenu,hMenu,0,IDM_CIRCLE2,offset szMenuCircle2 invoke AppendMenu,hMenu,MF_SEPARATOR,0,NULL invoke AppendMenu,hMenu,0,IDM_EXIT,offset szMenuExit invoke CheckMenuRadioItem,hMenu,IDM_CIRCLE1,IDM_CIRCLE2,IDM_CIRCLE1,NULL invoke CheckMenuRadioItem,hMenu,IDM_BACK1,IDM_BACK2,IDM_BACK1,NULL invoke CreateEllipticRgn,0,0,CLOCK_SIZE+1,CLOCK_SIZE+1 push eax invoke SetWindowRgn,hWinMain,eax,TRUE pop eax invoke DeleteObject,eax invoke SetWindowPos,hWinMain,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE or SWP_NOSIZE mov dwNowBack,IDB_BACK1 mov dwNowCircle,IDB_CIRCLE1 invoke _CreateBackGround invoke _CreateClockPic invoke SetTimer,hWinMain,ID_TIMER,1000,NULL ret _Init endp _ProcWinMain proc uses ebx edi esi hWnd,uMsg,wParam,lParam LOCAL @stPS:PAINTSTRUCT LOCAL @hDC LOCAL @stPos:POINT mov eax,uMsg .if eax == WM_TIMER invoke _CreateClockPic invoke InvalidateRect,hWnd,NULL,FALSE .elseif eax == WM_PAINT invoke BeginPaint,hWnd,addr @stPS mov @hDC,eax mov eax,@stPS.rcPaint.right sub eax,@stPS.rcPaint.left mov ecx,@stPS.rcPaint.bottom sub ecx,@stPS.rcPaint.top invoke BitBlt,@hDC,@stPS.rcPaint.left,@stPS.rcPaint.top,eax,ecx,hDcClock,@stPS.rcPaint.left,\ @stPS.rcPaint.top,SRCCOPY invoke EndPaint,hWnd,addr @stPS .elseifeax ==WM_CREATE mov eax,hWnd mov hWinMain,eax invoke _Init .elseif eax == WM_COMMAND mov eax,wParam .if ax ==IDM_BACK1 mov dwNowBack,IDB_BACK1 invoke CheckMenuRadioItem,hMenu,IDM_BACK1,IDM_BACK2,IDM_BACK1,NULL .elseif ax == IDM_BACK2 mov dwNowBack,IDB_BACK2 invoke CheckMenuRadioItem,hMenu,IDM_BACK1,IDM_BACK2,IDM_BACK2,NULL .elseif ax == IDM_CIRCLE1 mov dwNowCircle,IDB_CIRCLE1 invoke CheckMenuRadioItem,hMenu,IDM_CIRCLE1,IDM_CIRCLE2,IDM_CIRCLE1,NULL .elseif ax == IDM_CIRCLE2 mov dwNowCircle,IDB_CIRCLE2 invoke CheckMenuRadioItem,hMenu,IDM_CIRCLE1,IDM_CIRCLE2,IDM_CIRCLE2,NULL .elseif ax == IDM_EXIT call _Quit xor eax,eax ret .endif invoke _DeleteBackGround invoke _CreateBackGround invoke _CreateClockPic invoke InvalidateRect,hWnd,NULL,FALSE .elseif eax == WM_CLOSE call _Quit .elseif eax == WM_RBUTTONDOWN invoke GetCursorPos,addr @stPos invoke TrackPopupMenu,hMenu,TPM_LEFTALIGN,@stPos.x,@stPos.y,NULL,hWnd,NULL .elseif eax ==WM_LBUTTONDOWN invoke SetCursor,hCursorMove invoke UpdateWindow,hWnd invoke ReleaseCapture invoke SendMessage,hWnd,WM_NCLBUTTONDOWN,HTCAPTION,0 invoke SetCursor,hCursorMain .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 LoadCursor,hInstance,IDC_MOVE mov hCursorMove,eax invoke LoadCursor,hInstance,IDC_MAIN mov hCursorMain,eax invoke RtlZeroMemory,addr @stWndClass,sizeof @stWndClass invoke LoadIcon,hInstance,ICO_MAIN mov @stWndClass.hIcon,eax mov @stWndClass.hIconSm,eax push hCursorMain pop @stWndClass.hCursor 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,NULL,\ offset szClassName,offset szClassName,\ WS_POPUP or WS_SYSMENU,\ 100,100,CLOCK_SIZE,CLOCK_SIZE,\ 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




代码量确实有点长(相比其它语言来说...),由于这次的代码有一部分和上次的程序代码(上次写的WIN32时钟博客)有同样的操作。不再做总结,剩下的一部分须要注意的就是创建背景与时钟框(_CreateBackGround)与时钟的初始化(_Init)了。在创建背景的时候,非常easy利用两个自己定义的画刷将整个钟面背景填充作为背景,有意思的是对时钟框的操作。要将时钟框画到钟面上去。本程序中利用的是BitBlt()数据块传送函数。事实上就是把某个已经制作好的时钟框(提前制作好的位图文件)复制到指定的区域,当然假设是要拷贝的话。就要利用到ROP码(事实上就是源像素与目标像素的结合方式)了,由于做好的时钟框像素不是直接替换目标背景的像素。而是叠加到目标像素,由于黑色的颜色值为0。不论什么一种颜色与黑色进行OR操作都会是原来的颜色。不会改变。ROP码SRCPAINT就是将目标像素与源像素进行OR运算,所以首先将源像素与提前写好的MASK遮掩图片进行and操作(ROP码为SRCAND)将对应的位置与黑色叠加,然后再将源时钟框像素传送到目标时钟框,採用OR(ROP码为SRCPAINT)的操作,这样一个能够切换的时钟边框才干正常地显示出来。这也是本程序我感觉当时非常不好理解的一个地方。


以下就是关于时钟的初始化(_Init子函数),对于初始化。我的理解就是当时钟刚開始显示出来没有不论什么操作的时候显示的状态(包含一个弹出的窗体和背景。时钟框,形状等)


在敲代码的时候我也出现了一个非常低级的错误。在每一个子函数结束之前总会有一个ret指令,这个曾经在学DOS汇编的时候就应该已经知道了,它的意思就是:当某一行代码调用子函数的时候记住这一行代码的下一句代码的位置,当子函数调用完毕之后。在返回到这个位置继续运行,(我感觉就像是push  eip。  再pop   eip一样),代码分析到此结束。


以下来介绍本次程序用到的一些经常使用的API函数:


CreateComPatibleDC()
功能:
该函数创建一个与指定设备兼容的内存设备上下文环境(DC)。通过GetDc()获取的HDC直接与相关设备沟通,而本函数创建的DC,则是与内存中的一个表面相关联。
原型:
HDC CreateCompatibleDC(HDC hdc)
參数:
现有设备上下文环境的句柄。假设该句柄为NULL,该函数创建一个与应用程序的当前显示器兼容的内存设备上下文环境
返回值:
假设成功。则返回内存设备上下文环境的句柄;假设失败,则返回值为NULL。

CreateComPatibleBitMap()
功能:
该函数创建与指定的设备环境相关的设备兼容的位图。
原型:
HBITMAP CreateCompatibleBitmap(HDC hdc,int nWidth,int nHeight)。
參数:
hdc: 设备环境句柄。

nWidth:指定位图的宽度,单位为像素。 nHeight:指定位图的高度。单位为像素。 返回值: 假设函数运行成功,那么返回值是位图的句柄;假设函数运行失败,那么返回值为NULL。 CreatePatternBrush() 功能: 该函数能够创建具有指定位图模式的逻辑刷子,该位图不能是DIB类型的位图。DIB位图是由CreateDIBSection函数创建的。 原型: HBRUSH CreatePatternBrush(hbitmap) 參数: hbitmap:指向用于创建逻辑刷子的位图 返回值: 假设该函数运行成功。那么返回值标识为一个逻辑刷子,假设该函数运行失败,那么返回值为NULL。

PatBlt() 功能: 该函数使用当前选入指定设备环境中的刷子绘制给定的矩形区域。通过使用给出的光栅操作来对该刷子的颜色和表面颜色进行组合。 原型: BOOL PatBlt(HDC hdc, int nXLeft, int nYLeft, int nWidth, int nHeight, DWORD dwRop); 參数: hdc:设备环境句柄。

nXLeft:指定要填充的矩形左上角的X轴坐标,坐标按逻辑单位表示。 nYLeft:指定要填充的矩形左上角的Y轴坐标,坐标按逻辑单位表示。 nWidth:指定矩形的宽度,按逻辑单位表示宽度。 nHeight:指定矩形的高度,按逻辑单位表示高度。 dwRop:指定光栅操作码。

该操作码能够取下列值,这些值的含义例如以下: PATCOPY:将指定的模式复制到目标位图中。

PATINVERT:使用布尔XOR(异或)操作符将指定模式的颜色与目标矩形的颜色进行组合。 DSTINVERT:将目标矩形反向。

BLACKNESS:使用物理调色板中与索引0相关的颜色填充目标矩形。(对于缺省的物理调色板而言,该颜色为黑色)。 WHITENESS:使用物理调色板中与索引1有关的颜色来填充目标矩形。

(对于缺省的物理调色板而言,该颜色为白色)。

返回值: 假设函数运行成功,则返回值为非零;假设函数运行失败,则返回值为0。

CreateElliPticRgn() 功能參数: 创建一个椭圆区域。 (注:_In_ 表示该參数为输入參数) x1 指定椭圆外接矩形左上角的逻辑横坐标。 y1 指定椭圆外接矩形左上角的逻辑纵坐标。 x2 指定椭圆外接矩形右下角的逻辑横坐标。 y2 指定椭圆外接矩形右下角的逻辑纵坐标。 原型: HRGN CreateEllipticRgn( _In_ int nLeftRect, _In_ int nTopRect, _In_ int nRightRect, _In_ int nBottomRect) 返回值: 操作成功返回该区域的句柄,否则为NULL。 SetWindowRgn() 功能: 函数是设置了一个窗体的区域.仅仅有被包括在这个区域内的地方才会被重绘,而不包括在区域内的其它区域系统将不会显示. 原型: int SetWindowRgn(HWND hWnd, HRGN hRgn, BOOL bRedraw); int SetWindowRgn(HRGN hRgn,BOOL bRedraw); 參数: hWnd:窗体的句柄 hRgn: 指向的区域.函数起作用后将把窗体变成这个区域的形状. 假设这个參数是空值,窗体区域也会被设置成空值,也就是什么也看不到. 返回值: 假设函数运行成功,就返回非零的数字.假设失败,就返回零 GetWindowRgn() 功能: 获取窗体的区域。仅仅有被包括在这个区域内的地方才会被重绘,而不包括在区域内的其它区域系统将不会显示 原型: int GetWindowRgn(HWND hWnd, HRGN hRgn); 參数: hWnd:窗体的句柄 hRgn:指向的区域 返回值: 返回值指定函数获取区域的类型。

它能够是下列值之中的一个: NULLREGION 该区域为空。 SIMPLEREGION 该区域是一个矩形。

COMPLEXREGION 该区域是多个矩形。 ERROR 发生错误;该区域不受影响。

SetCursor() 功能: 该函数确定光标的形状 原型: HCURSOR SetCursor(HCURSOR hCursor); 參数: hCursor:光标的句柄,该光标由CreateCursor函数加载。假设该參数为NULL,则该光标从屏幕上移开。在Windows95中该光标的宽和高是GetSystemMetrics 函数的返回值SM_CXCURSOR和SM_CYCURSOR,而且光标的位深必须和显示器的位深相匹配,或者光标是单色的。 返回值: 假设有前一个光标,则返回值是前光标的句柄;假设没有前光标。则返回值是NULL。 ReleaseCapture() 功能: 函数功能是该函数从当前线程中的窗体释放鼠标捕获。并恢复通常的鼠标输入处理 原型: BOOL ReleaseCapture(VOlD) 參数: 无 返回值: 假设函数调用成功。返回非零值。假设函数调用失败,返回值是零。 TransparentBlt() 功能: 该函数对指定的源设备环境中的矩形区域像素的颜色数据进行位块(bit_block)转换,并将结果置于目标设备环境。

原型: BOOL TransparentBlt(HDC hdcDest, int nXOriginDest, int nYOriginDest, int nWidthDest, int hHeightDest, HDC hdcSrc, int nXOriginSrc, int nYOriginSrc, int nWidthSrc, int nHeightSrc, UINT crTransparent)。 參数: nXOriginDest:指定目标矩形左上角的X轴坐标,坐标以逻辑单位表示。 nYOriginDest:指定目标矩形左上角的Y轴坐标,坐标以逻辑单位表示。 。 nHeightDest:指定目标矩形的高度。

。 nXOriginSrc:指定源矩形(左上角)的X轴坐标。坐标以逻辑单位表示。 nYOriginsrc:指定源矩形(左上角)的Y轴坐标,坐标以逻辑单位表示。 nWidthSrc:指定源矩形的宽度。 nHeightSrc:指定源矩形的高度。 crTransparent:源 位图中的RGB值当作透明颜色。

(用RGB(0,0,0)也就是黑色不行) 返回值: 假设函数运行成功。那么返回值为TRUE;假设函数运行失败,那么返回值为FALSE SetwindowPos() 功能: 改变一个子窗体。弹出式窗体或顶层窗体的尺寸。位置和Z序。子窗体,弹出式窗体,及顶层窗体依据它们在屏幕上出现的顺序排序、顶层窗体设置的级别最高,而且被设置为Z序的第一个窗体。 原型: WINUSERAPI BOOL WINAPI SetWindowPos(HWND hWnd,HWND hWndInsertAfter,int X,int Y,int cx,_In_ int cy, UINTuFlags); 參数: pWndInsertAfter 用于标识在z-顺序的此 CWnd 对象之前的 CWnd 对象。 hWndlnsertAfter 在z序中的位于被置位的窗体前的窗体句柄。

该參数必须为一个窗体句柄。或下列值之中的一个: HWND_BOTTOM:将窗体置于Z序的底部。假设參数hWnd标识了一个顶层窗体。则窗体失去顶级位置。而且被置在其它窗体的底部。 HWND_NOTOPMOST:将窗体置于全部非顶层窗体之上(即在全部顶层窗体之后)。

假设窗体已经是非顶层窗体则该标志不起作用。

HWND_TOP:将窗体置于Z序的顶部。 HWND_TOPMOST:将窗体置于全部非顶层窗体之上。即使窗体未被激活窗体也将保持顶级位置。

查看该參数的用法,请看说明部分。 x 以客户坐标指定窗体新位置的左边界。 Y 以客户坐标指定窗体新位置的顶边界。 cx 以像素指定窗体的新的宽度。 cy 以像素指定窗体的新的高度。 uFlags 窗体尺寸和定位的标志。

该參数能够是下列值的组合: SWP_ASYNCWINDOWPOS:假设调用进程不拥有窗体,系统会向拥有窗体的线程发出需求。

这就防止调用线程在其它线程处理需求的时候发生死锁。 SWP_DEFERERASE:防止产生WM_SYNCPAINT消息。 SWP_DRAWFRAME:在窗体周围画一个边框(定义在窗体类描写叙述中)。

SWP_FRAMECHANGED:给窗体发送WM_NCCALCSIZE消息,即使窗体尺寸没有改变也会发送该消息。假设未指定这个标志。仅仅有在改变了窗体尺寸时才发送WM_NCCALCSIZE。 SWP_HIDEWINDOW;隐藏窗体。

SWP_NOACTIVATE:不激活窗体。假设未设置标志。则窗体被激活,并被设置到其它最高级窗体或非最高级组的顶部(依据參数hWndlnsertAfter设置)。 SWP_NOCOPYBITS:清除客户区的全部内容。假设未设置该标志,客户区的有效内容被保存而且在窗体尺寸更新和重定位后拷贝回客户区。 SWP_NOMOVE:维持当前位置(忽略X和Y參数)。

SWP_NOOWNERZORDER:不改变z序中的全部者窗体的位置。 SWP_NOREDRAW:不重画改变的内容。假设设置了这个标志,则不发生不论什么重画动作。

适用于客户区和非客户区(包括标题栏和滚动栏)和不论什么因为窗回移动而露出的父窗体的全部部分。假设设置了这个标志,应用程序必须明白地使窗体无效并区重画窗体的不论什么部分和父窗体须要重画的部分。

SWP_NOREPOSITION:与SWP_NOOWNERZORDER标志同样。 SWP_NOSENDCHANGING:防止窗体接收WM_WINDOWPOSCHANGING消息。 SWP_NOSIZE:维持当前尺寸(忽略cx和Cy參数)。 SWP_NOZORDER:维持当前Z序(忽略hWndlnsertAfter參数)。 SWP_SHOWWINDOW:显示窗体。 返回值: 假设函数成功,返回值为非零。假设函数失败,返回值为零 CreatepopupMenu() 功能: 创建一个下拉式菜单、子菜单或快捷菜单。

此菜单最初是空的。但可用函数InsertMenultem来插入或追加菜单项。

也可用函数InsertMenu来插入菜单项,用AppendMenu来追加菜单项。 原型: HMENU CreatePopupMenu(VOID) 參数: 无 返回值: 假设函数调用成功。返回值是新创建菜单的句柄。假设函数调用失败,返回值是NULL。


















posted @ 2017-07-28 13:57  zhchoutai  阅读(882)  评论(0编辑  收藏  举报