win32笔记

我应该知道:
1、WM_PAINT优先级很低, 基本总是处于消息队列尾部, 要实时重绘 可调用 UpdateWindow(hwnd);
2、windows很多结构第一个字段常被定义为sizeof(this); 目的是方便以后的版本可以扩充结构而保持与以前程序兼容
3、6种GDI对象

CBitMap - 位图是一种位矩阵,每一个显示像素都对应一个或多个位,我们可以用位图来表示图像,也可以用它来创建刷子。
CBrush - 刷子定义了一种位图形式的像素,用它可以对区域内部填充颜色。
CFont - 字体是一种具有某种风格和尺寸的所有字符的集合。
CPalette - 调色板是一种颜色映射接口。
Cpen - 笔是一种画线和有形边框的工具,可以指定画线的宽度,以及画虚线,实线等。
CRgn - 区域是一种范围,可以用它来填充、裁剪以及鼠标点中测试。
4、3条规则控制GDI对象的使用
最终应当删除创建的所有GDI对象
当GDI对象被选入一个有效的设备环境时 不要删除它
不要删除备用对象

#define WINAPI __stdcall
typedef unsigned short wchar_t;
strlen(char) ASCII字符 wcslen(wchar_t) 宽字符
TCHAR.h 头文件处理了 兼容ASCII和宽字符的函数集
TEXT() 宏可根据编码环境处理字符串为ASCII字符或宽字符
funA()->ascii版 funW()->宽字符版

打印信息: (在vcvs的空项目都能运行,vs的win32prj不可运行)
char szBuffer[100];
sprintf(szBuffer, “the value is %d”, val);
MessageBox(NULL, szBuffer, “msg”, MB_OK);
// win32prj中 第二个参数有问题 解决方案1:类型强转(LPCSTR)
int GetSystemMetrics(int nIndex) 获取windows的窗口大小
nIndex = SM_CXSCREEN|SM_CYSCREEN (x轴像素点|压轴像素点)


typedef struct tagMSG {
    HWND     hwnd;        消息所指向的窗口句柄
    UINT    message;    消息标识符 大多数定义于WINUSER.H
    WPARAM    wParam;        一个32位消息参数 意义和取值取决于具体消息
    LPARAM    lParam;        同上
    DWORD    time;        消息进入消息队列的时间
    POINT    pt;            消息进入消息队列中时鼠标指针的位置坐标
} MSG, *PMSG;
typedef struct tagPOINT {
    long x; long y;
} POINT, *PPOINT;

GetMessage(&msg, NULL, 0, 0);
函数像操作系统发送请求 获取要处理的消息 如果消息队列中检索到的消息的message字段不等于WM_QUIT(其值为0x0012),
则GetMessage将返回一个非0值,否则返回0

点击关闭按钮会产生一个WM_SYSCOMMAND消息 交由DefWindwoProc处理 发送一条WM_CLOSE消息 又交由DefWindwoProc处理
调用DestoryWindow(产生了WM_DESTORY消息?) 函数中调用PostQuitMessage 发送一条WM_QUIT消息 结束消息循环

消息既可以是”队列消息” 也可以是”非队列消息” 队列消息是指由windows放入程序的消息队列中的消息 在程序的消息循环中
消息被检索 然后被投递到窗口过程中 非队列消息则是由windows对窗口过程的直接调用而产生的
队列消息一般是”投递”(post)到消息队列中 而非队列消息则是被”发送”(send)到窗口过程
队列消息主要由用户的输入产生,主要形式为按键消息(例如 WM_KEYDOWN和WM_KEYUP) 由按键产生的字符消息(WM_CHAR)
鼠标移动(WM_MOUSEMOVE) 鼠标单击(WM_LBUTTONDOWN)
此外 队列消息还包括定时器消息(WM_TIMER) 重绘消息(WM_PAINT) 和退出消息(WM_QUIT)
非队列消息则包括队列消息以外的其它所有消息 非队列消息通常由调用特定的windows函数引起 例如 WinMain调用createWindow
会在创建窗口过程中向窗口过程发送一个WM_CREATE消息 而当WinMain调用showwindow时会发送WM_SIZE 和WM_SHOWWINDOW
updatewindow会发送 WM_PAINT
表明键盘或鼠标输入的队列消息也能产生非队列消息 例如 当键盘或鼠标选择某个菜单项时 键盘或鼠标消息会进入消息队列
而最终表明有某菜单项被选中的WM_COMMAND消息却是一个非队列消息
p86 关于消息处理的几段话没有看明白

WM_PAINT优先级很低, 基本总是处于消息队列尾部, 要实时重绘 可调用 UpdateWindow(hwnd);

#define LOWORD(l) ((WORD)(l))

#define HIWORD(l) ((WORD)(((WORD)(l)>>16)&0xffff))

SetScrollRange(hwnd, iBar, iMin, iMax, bRedraw); 设置滚动条范围
iBar=[SB_VERT|SB_HORZ] iMin,iMax分别对应范围最小最大值 bRedraw是否重绘
如果在调用SetScrollRange函数之后还调用其它函数来调整滚动条的显示时 最好将bRedraw设置为FALSE以避免过多重绘
SetScrollPos(hwnd, iBar, iPos, bRedraw); 设置滑块位置
GetScrollRange() GetScrollPos() 获取滚动条的范围和当前位置
用户点击滚动条或滑块时会产生 WM_VSCROLL或WM_HSCROLL 消息 并伴随 鼠标按下 和 鼠标松开两条消息
WM_VSCROLL和WM_HSCROLL的lParam一般可忽略 它只用于滚动条是子窗口时 通常是在对话框中
wParam低字节代表了鼠标在滚动条上的操作 由一个以SB开头的标识符定义 wParam的高字节是用户拖动滑块的当前位置
如果在滚动条的不同部分按住鼠标不动,程序可能收到多条滚动条消息
当松开鼠标键时 程序会受到一条带有SB_ENDSCROLL通知码消息
将鼠标放在滑块上然后按下鼠标键时,可以移动滑块,会生成带SB_THUMBTRACK和SB_THUMBPOSITION通知码的消息
当wParam的低字节是SB_THUMBTRACK时,wParam的高字节是用户拖动滑块的当前位置,这个位置位于range内
当wParam的低字节是SB_THUMBPOSITION时 wParam的高字节是用户松开鼠标的最终位置 对于其他滚动条操作 wParam高字节应被忽略
很少同时处理这两个消息, 区别是前者实时更新界面 后者当滑块停止时更新界面
新引入的两个函数 SetScrollInfo GetScrollInfo 包含上述四个功能 还加入两个新功能 设定滑块大小 获得超过16位的滑块位置
wParam高字节存放的滑块位置只有16位 当数据超过65535后 无法表示 而GetScrollInfo可以处理
SetScrollInfo(hwnd, iBar, &si, bRedraw);
GetScrollInfo(hwnd, iBar, &si);
iBar=[SB_VERT|SB_HORZ|SB_CTL] CTL表示一个滚动条控件


si = typedef struct tagSCROLLINFO {
    UINT cbSize;    // 设置为sizeof(SCROLLINFO)    
    UINT fMask;        // 要设置或获取的值
    int nMin;        // 范围最小值    
    int nMax;        // 范围最大值
    UINT nPage;        // 页面大小
    int nPos;        // 当前位置
    int nTrackPos;    // 当前追踪位置
} SCROLLINFO, *PSCROLLINFO;

windows很多结构第一个字段常被定义为sizeof(this); 目的是方便以后的版本可以扩充结构而保持与以前程序兼容
fMask字段是一个或多个以SIF为前缀的标志

iValue = GetDevicesCaps(hdc, iIndex);
获取设备的信息 包括显示器的大小和它的色彩能力等
参数iIndex是定义在WINGDI.H中的29个标识符之一,标志返回的信息

分辨率:每英寸像素点 像素尺寸:水平或垂直总像素点 度量尺寸:每英寸或毫米为单位的设备的客户区大小
像素尺寸 / 度量尺寸 = 分辨率;
5.2.4 设备的尺寸 133 全程懵逼

COLORREF(32位无符号长整型)来表示一种特定的颜色 0-7:R 8-15:G 16-23:B 24-31:0

#define RGB(r,g,b) ((COLORREF)(((BYTE)(r)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(b))<<16)))
GetRValue、GetGValue、GetBValue宏从COLORREF值中提取RGB颜色值

绘图函数
SetPixel(hdc, x, y, (COLORREF)crColor); 将坐标为(x,y)的像素点设定为某个特定的颜色
(COLORREF)crColor = GetPixel(hdc, x, y); 获取坐标为(x,y)的像素点的颜色值
MoveTo(hdc, x, y);(16位windows) 返回值是调用之前点坐标
MoveToEx(hdc, xBeg, yBeg, NULL); 最后一个参数指向一个POINT的指针 记录调用之前点位置
LineTo(hdc, xEnd, yEnd);
GetCurrentPositionEx(hdc, &pt); 获取当前点坐标 pt是POINT对象
Polyline(hdc, apt, n); apt点数组 n数组长度 顺序连接apt中的点
Rectangle(hdc, xLeft, yTop, xRight, yBottom); 绘制矩形 不包含右边和下边界点
Ellipse(hdc, xLeft, yTop, xRight, yBottom); 绘制椭圆内切外面的矩形框
RoundRect(hdc, xLeft, yTop, xRight, yBottom, xCornerEllipse, yCornerEllipse); 绘制圆角矩形 后两个参数是在角落画椭圆
Arc (hdc, xLeft, yTop, xRight, yBottom, xStart, yStart, xEnd, yEnd); 绘制椭圆从(xStart,yStart)->(xEnd,yEnd)的曲线
Chord (hdc, xLeft, yTop, xRight, yBottom, xStart, yStart, xEnd, yEnd); 在上一个基础上连接首尾直线的封闭曲线
Pie (hdc, xLeft, yTop, xRight, yBottom, xStart, yStart, xEnd, yEnd); 在第一个基础上连接首-椭圆中心-尾的折线

画笔
HPen = GetStockObject(WHITE_PEN | BLACK_PEN | NULL_PEN); 可以获取备用画笔的句柄 白色 黑色 无画笔
HPen = SelectObject(hdc, hPen); 将画笔选入设备环境 返回前一个画笔的句柄
SelectObject(hdc, GetStockObject(WHITE_PEN)); 组合使用
创建画笔 CreatePen或者CretePenIndirect创建一个逻辑画笔 返回逻辑画笔的句柄
调用SelectObject将画笔传入设备环境中
释放设备环境之后 或者将其它画笔选入设备环境之后 需要调用DeleteObject释放画笔

创建画笔 CreatePen和CretePenIndirect不需要hdc
HPEN hpen = CreatePen(iPenStyle, iWidth, crColor);
iPenStyle决定画笔绘制的是实现还是虚线或者点线PS_SOLID|PS_DASH|PS_DOT|PS_DASHDOT|PS_DASHDOTDOT|PS_NULL|PS_INSIDEFRAME
对于PS_SOLID PS_NULL PS_INSIDEFRAME样式 参数iWidth表示画笔的宽度 当iWidth=0时 画笔宽度为1ps 备用画笔总是1ps宽
如果指定虚线或点线宽度大于1 windows会使用实心画笔来代替 (意思就是iWidth只能=1)
crColor是一个COLORREF值 指定画笔的颜色 对所有除PS_INSIDEFRAME之外的样式 windows自动将该颜色转换为能表示的最近的纯色
PS_INSIDEFRAME样式是唯一能够使用抖动色的画笔样式 并且只有当画笔宽度大于1时才如此
也可以通过建立一个类型为LOGPEN(逻辑画笔)的结构 并调用CreatePenIndirect函数来建立一个画笔
LOGPEN logpen; 这个结构有三个字段 (UINT)lopenStyle表示画笔样式 (POINT)lopnWidth以逻辑单位表示的画笔宽度
还有(COLORREF)lopnColor表示画笔的颜色 windows仅使用lopnWidth中的x设置画笔宽度 y被忽略
hPen = CreatePenIndirect(&logpen);

SelectObject(hdc, hPen);
DeleteObject(hpen);
hPen = SelectObject(hdc, CreatePen(PS_DASH, 0, RGB(255,0,0)));
DeleteObject(SelectObject(hdc, hPen));

GetObject(hPen, sizeof(LOGPEN), (LPVOID)&logpen); 获取LOGPEN结构中各个字段成员的值
hPen = GetCurrentObject(hdc, OBJ_PEN); 获取当前被选入设备环境的画笔句柄

填充虚线和点线画笔间的空隙 由设备环境的背景模式和背景颜色共同决定
默认背景模式是OPAQUE(不透明) 空隙使用背景色(默认白色)填充
可以使用SetBkColor(hdc, crColor);设置文字背景色 GetBkColor获取背景色
SetBkMode(hdc, TRANSPARENT(透明)); 设置背景模式透明 阻止windows填充背景色
GetBkMode(); 可以获取当前当前背景模式 要么是TRANSPARENT 要么是OPAQUE

在设备环境中绘制线条 其颜色由画笔和显示区域的颜色共同确定 对两个颜色使用ROP2(二元光栅操作)得出显示颜色
windows定义了16种ROP2运算码 默认设备环境中绘图模式是R2_COPYPEN 将画笔像素颜色复制到目标像素上
博客中叙述了16中运算模式http://blog.csdn.net/hopygreat/article/details/78950875
可以调用SetROP2(hdc, iDrawMode); 设置绘图模式
可以调用iDrawMode = GetROP2(hdc); 获取当前绘图模式

画刷
Windows使用当前选入设备环境的画刷来填充图形,在默认情况下 使用的是备用对象WHITE_BRUSH(白色)
Windows定义了6种备用画刷:WHITE_BRUSH, LTGRAY_BRUSH, GRAY_BRUSH, DKGRAY_BRUSH,
BLACK_BRUSH, NULL_BRUSH(又称为HOLLOW_BRUSH)
HBRUSH hBrush = GetStockObject(WHITE_BRUSH);可获取备用画刷
SelectObject(hdc, hBrush); 可以将画刷选入设备环境中
SelectObject(hdc, GetStockObject(NULL_PEN)); 可以绘制一个不含边框的图形
SelectObject(hdc, GetStockObject(NULL_BRUSH)); 可以绘制一个只含边框的图形
Polygon(hdc, apt, iCount); 绘制多边形 apt是POINT数组 iCount是点个数 如果最后一个点和第一个点不同 会自动连接一条线
PolyPolygon(hdc, apt, aiCounts, iPolyCount); 绘制多个多边形 apt是所有点数组
aiCounts给出每个多边形顶点数 iPolyCount给出多边形个数
对Polygon, PolyPolygon windows都使用设备环境中的当前画刷来填充区域,至于内部是如何填充的 要取决于多边形填充模式
可以调用SetPolyFillMode(hdc, iMode)来设置填充模式
默认情况下 多边形填充模式是ALTERNATE(交替),但是也可以将它设定为WINDING(螺旋) 较复杂 仅这两种选择 P164

创建画刷: windows允许使用5种函数来创建画刷 调用SelectObject将画笔传入设备环境中
hBrush = CreateSolidBrush(crColor);
hBrush = CreateHatchBrush(iHatchStyle, crColor); 创建阴影线标记画刷
iHatchStyle = [HS_HORIZONTAL | HS_BDIAGONAL | HS_VERTICAL | HS_CROSS | HS_FDIAGONAL | HS_DIAGCROSS]
此处存在填充线和背景色混合问题 背景模式 阴影线颜色 背景颜色
CreatePatternBrush() 和 CreateDIBPatternBrushPt() 创建位图画刷
hBrush = CreateBrushIndirect(&logbrush); 包含上述四个功能 logbrush是LOGBRUSH结构的逻辑画刷对象
LOGPEN logbrush; 这个结构有三个字段 (UINT)lbStyle (COLORREF)lbColor (LONG)lbHatch


lbStyle字段的值决定着windows如何解释其他两个字段

lbStyle            lbColor         lbHatch
BS_SOLID           画刷的颜色      忽略
BS_HOLLOW          忽略            忽略
BS_HATCHED         阴影线的颜色    阴影线的样式
BS_PATTERN         忽略            位图句柄
BS_DIBPATTERNPT    忽略            指向DIB的指针

GDI映射模式mapping mode
与映射模式相关的有四个其他的设备环境属性 窗口原点 视口原点 窗口范围 视口范围
GDI函数中的坐标是逻辑坐标 windows要把其转换为设备单位 即像素


METRIC(公制) ENGLISH(英制) LO HI是低高精度    Twip杜撰词1/20点  1点=1/72英寸
isotropic anisotropic是各向同性 各向异性
映射模式        逻辑单位        x轴     y轴     值增加方向 
MM_TEXT         像素            右      下      (默认)
MM_LOMETRIC     0.1mm           右      上
MM_HIMETRIC     0.01mm          右      上
MM_LOENGLISH    0.01in.         右      上
MM_HIENGLISH    0.001in.        右      上
MM_TWIPS        1/1440in.       右      上
MM_ISOTROPIC    自定义(x=y)     自定义  自定义
MM_ANISOTROPIC  自定义(x!=y)    自定义  自定义

SetMapMode(hdc, iMapMode); 设置映射模式
iMapMode = GetMapMode(hdc); 获取映射模式

5.5.3 视图和窗口 172
ClientToScreen函数可以将客户区坐标转换为屏幕坐标 反之ScreenToClient
GetWindowRect函数以屏幕坐标的形式获取整个窗口的位置和大小
DPtoLP(hdc, pPoints, iNumber); 将设备点转换为逻辑点 pPoints是一个指向POINT数组的指针 iNumber是要转换的点个数
LPtoDP(hdc, pPoints, iNumber); 将逻辑点转换为设备点

win32消息机制常用消息
WM_CLOSE: 点右上角×,默认消息处理时会发送WM_DESTORY
WM_DESTORY: 窗口被销毁
WM_CREAT: 窗口被创建
WM_PAINT: 窗口重绘
WM_COMMAND: 点击按钮
WM_SIZE: 窗口大小改变 lParam的低字节 客户区cx 高字节 客户区cy
WM_LBUTTONDOWN: 鼠标左键点击 wparam低字节 鼠标x坐标 高字节y
WM_RBUTTONDOWN: 鼠标右键点击 wparam低字节 鼠标x坐标 高字节y
WM_MOUSEMOVE: 鼠标移动 wparam低字节 鼠标x坐标 高字节y

BOOL MoveWindow(HWND hWnd.int x.int y,int nWidth,int nHeight,BOOL BRePaint(窗口是否被重绘));
BOOL SetWindowText(HWND hwnd,LPCTSTR lpString);
int DialogBox(HINSTANCE hlnstance,LPCTSTRIpTemplate,HWND hWndParent,DLGPROC IpDialogFunc);
BOOL CALLBACK DialogProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM IParam);
UINT GetDlgltemlnt(HWND hDlg,int nlDDlgltem,BOOL *IpTranslated,BOOL bSigned);
BOOL SetDlgltemlnt(HWND hDlg,int nLDDlgltem,UINT uValue,BOOL bSigned);
HWND GetDlgltem(HWND hDlg,int nlDDlgltem);
BOOL GetWindowRect(HWND hWnd,LPRECTlpRect);
BOOL GetCursorPos(LPPOlNT IpPoint);
string.format(“%s”, charArr); 将字符数值转换为字符串

DialogBox函数可显示rc文件里的对话框资源
函数原型:int DialogBox(HINSTANCE hlnstance,LPCTSTRIpTemplate,HWND hWndParent,DLGPROC IpDialogFunc);
返回值, 实例句柄, dlgID, 窗口句柄, 回调函数

DialogProc 对话框消息处理函数
BOOL CALLBACK DialogProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam);
除了对MM_INITDIALOG消息的响应之外如果函数处理消息,则对话框应用程序应该返回非零值,否则返回0
对话框句柄, msg, wParam, lParam

获取对话框指定ID的文本转化为int
UINT GetDlgItemInt(HWND hDlg,int nlDDlgltem,BOOL *IpTranslated,BOOL bSigned);
值, 对话框句柄, ID, 函数调用是否成功返回值(一般设为null), 是否是有符号数

将值设定到指定ID位置
BOOL SetDlgltemlnt(HWND hDlg,int nLDDlgltem,UINT uValue,BOOL bSigned);
函数调用是否成功, 对话框句柄, ID, 写入值, 是否是有符号数


对话框退出代码
switch(uMsg)
{
    case WM_COMMAND:
    {
        if ( LOWORD(wParam) == IDCANCEL )
        {
            // 句柄+返回值
            EndDialog( hwndDlg, IDCANCEL );
            return true;
        }
    }
}

当对话框还未显示出来的时候会产生一个WM_INITDIALOG消息

CListCtrl的InsertColumn可以在列表框中添加表头
// 获取列表框句柄
CListCtrl pList = (CListCtrl)GetDlgItem(IDC_LIST1);
// 插入 列号(0开始),标题, 左对齐, 大小
pList->InsertColumn( 0, “学号”, LVCFMT_LEFT, 120 );
使用InsertColumn的前提是列表框的style->查看->报告

GetItemCount(); 获得列表框的行数
InsertItem( ID, str ); 将str插入到列表框的第一列
SetItemText( count, n, str ); 在列表框的第count行的第n+1列插入str

GetSelectionMark(); 获取虚线框选中项的行号
DeleteItem( nSel ); 删除列表框中的第nSel行

POSITION pos = pList->GetFirstSelectedItemPosition();
int nSel = pList->GetNextSelectedItem(pos);
基于蓝色框选中的位置

pList->GetSelectedCount(); 返回列表视图中被选择的项数
结合GetSelectionMark()

pList->SetExtendedStyle(LVS_EX_FULLROWSELECT); 设置一次选中一行

mfc核心头文件afxwin.h 核心方法virtual BOOL InitInstance(){}
需在有一个CWinApp的派生类 并有一个全局派生类对象


class CMyApp : public CWinApp
{
    virutal BOOL InitInstance()
    {
        statment;
        return true/false;
    }
};
CMyApp xxx;