3.1.1 Win32_Note
Win32 Note
day01
Windows应用程序的类型
控制台程序 Console
DOS程序,本身没有窗口,通过Windows DOS窗口执行
窗口程序
拥有自己的窗口,可以与用户交互
库程序
存放代码、数据的程序,执行文件可以从中取出代码执行和获取数据
-静态库程序
扩展名LIB,在执行文件执行时从中获取代码
-动态库程序
扩展名DLL,在编译链接程序时,将函数地址放入到执行文件中
- 三种应用程序的对比
-入口函数
控制台程序 - main
窗口程序 - WinMain
动态库程序 - DllMain
静态库程序 - 无入口函数
-文件存在方式
控制台程序、窗口程序 - EXE文件
动态库程序 - DLL文件
静态库程序 - LIB文件
-执行方式
控制台程序 - 在DOS窗口内执行。
窗口程序 - 拥有自己的窗口在自己的窗口内执行.
动态库程序 - 本身无法执行,由可执行程序或其他的DLL调用
静态库程序 - 执行不存在,代码会嵌入到可执行文件或DLL等中。
- Windows开发工具和库
- 开发工具 Visual Studio C++
VC1.5 - VC6.0 – VC2005-VC2010( 10.0 )
WIN31-WIN32-WIN95-WIN98-2000-XP-……
- VC的编译工具
编译器CL.EXE 将源代码编译成目标代码
链接器LINK.EXE 将目标代码、库链接生成最终文件
资源编译器RC.EXE 将资源编译,最终通过链接器存入最终文件(.rc)
- Windows库和头文件
- Windows库
kernel32.dll - 提供了核心的API,例如进程、线程、内存管理等。
user32.dll - 提供了窗口、消息等API
gdi32.dll - 绘图相关的API
-头文件
windows.h - 所有windows头文件的集合
windef.h - windows数据类型
winbase.h - kernel32的API
wingdi.h - gdi32的API
winuser.h - user32的API
winnt.h - UNICODE字符集支持
int WINAPI WinMain(
HINSTANCE hInstance,//当前程序的实例句柄
HINSTANCE hPrevInstance, //当前程序前一个实例句柄
LPSTR lpCmdLine,//命令行参数字符串
int nCmdShow //窗口的显示方式
);
hPrevInstance - Win32下,一般为NULL
int MessageBox(
HWND hWnd,//父窗口句柄
LPCTSTR lpText, //显示在提示框中的文字
LPCTSTR lpCaption, //显示在标题栏中的文字
UINT uType //提示框中的按钮、图标显示类型
);// 返回点击的按钮ID
编译环境准备
VC98\BIN\VCVARS32.BAT
编译程序 - CL
CL.EXE -? 显示CL的帮助
/c 只编译不链接
/Tc 编译C文件
/Tp 编译C++文件
- 链接程序 - LINK
LINK.EXE xxx.obj xxx.lib
执行
编写窗口程序的步骤:
1 定义WinMain函数
2 定义窗口处理函数 (处理消息)
3 注册窗口类(向XP系统中写入一些数据)
4 创建窗口 (在内存中将窗口创建出来)
5 显示窗口(根据内存中的数据将窗口绘制出来)
6 消息循环(提取/翻译/派发 消息)
7 消息处理
- 编写资源的文件 -.rc资源脚本文件
- 编译rc文件 - RC.EXE
- 将资源链接到程序中 - LINK.EXE
day02
ASC - 7位代表一个字符 128个字符
ASCII - 8位代表一个字符 256个字符
代码页(CodePage)
DBCS - 单双字节混合编码(主流编码方式)
A 我 是 程 序 员
01 0203 0405 0607 0809 0A0B
0102 0304 0506 0708 090A 0B
UNICODE
A 我 是 程 序 员
0001 0203 0405 0607 0809 0A0B
#ifdef UNICODE
typedef wchar_t TCHAR;
#define __TEXT(quote) L##quote
#else
typedef char TCHAR;
#define __TEXT(quote) quote
#endif
BOOL WriteConsole(
HANDLE hConsoleOutput, //标准输出句柄
CONST VOID *lpBuffer, //输出内容的buff
DWORD nNumberOfCharsToWrite, //准备输出的长度
LPDWORD lpNumberOfCharsWritten,
//返回实际输出的长度,可以为NULL
LPVOID lpReserved // 备用,NULL
);
HANDLE GetStdHandle(
DWORD nStdHandle
// STD_INPUT_HANDLE,STDOUTPUT_HANDLE,
// STD_ERROR_HANDLE
);//返回值 返回相应的句柄
控制面板 ->Visual Assist X
day03
BOOL MoveWindow(
HWND hWnd, // 窗口句柄
int X, // x坐标
int Y, // y坐标
int nWidth, // 窗口的宽度
int nHeight, // 窗口的高度
BOOL bRepaint // 是否擦除原来绘制的图像
);
ShowWindow( hWnd,SW_SHOW )
{
根据hWnd-->保存窗口数据的内存-->
从内存提取窗口必要数据-->....
}
1 窗口类附加数据缓冲区用法
1.1 申请缓冲区
int cbClsExtra - 一般赋4的倍数
1.2 向buff写数据
DWORD SetClassLong(
HWND hWnd, // 窗口句柄
int nIndex, // 字节索引号(从哪个字节开始存)
LONG dwNewLong // 存入的数据
);
1.3 从buff中读数据
DWORD GetClassLong(
HWND hWnd, // 窗口句柄
int nIndex // 字节索引号(从哪个字节开始读)
);//返回值获取读取的数据
2 窗口附加数据缓冲区的用法
2.1 申请缓冲区
int cbWndExtra - 一般赋4的倍数 200
2.2 向buff中写入数据
LONG SetWindowLong(
HWND hWnd, // 窗口句柄
int nIndex, // 字节索引号(从哪个字节开始存)
LONG dwNewLong // new value
);
2.3 从buff中读取数据
LONG GetWindowLong(
HWND hWnd, // 窗口句柄
int nIndex // 字节索引号(从哪个字节开始读)
);//返回值获取 读取的数据
区别:
窗口类附加数据缓冲区:是基于同一窗口类创建出来的所有窗口共享的缓冲区
窗口附加数据缓冲区:是窗口自己私有的缓冲区,即便是基于同一个窗口类创建出来的窗口相互之间也不共享
long a = 1563456;
a & 0x0000FFFF
a >> 16 & 0x0000FFFF
int x = LOWORD(lParam);
int y = HIWORD(lParam);
day04 / 05
SendMessage(.....)
{
.......
return WndProc(....);
}
TranslateMessage( &nMsg )
{
if( nMsg.message != WM_KEYDOWN )
return...;
根据nMsg.wParam(虚拟简码值)获知哪个按键被按下
if( 不是 )
return...;
if( 是 )
{
判断CapsLock(大写锁定键)是否处于打开状态
if(打开)
PostMessage( nMsg.hwnd,WM_CHAR, 0x41,....);
else
PostMessage( nMsg.hwnd,WM_CHAR, 0x61,....);
}
}
TranslateMessage( &nMsg )
{
if( nMsg.message != WM_KEYDOWN )
return ...;
根据 wParam(键码值)来获知哪个按键被按下
if( 不是 )
return...;
if( 是 )
{
判断CAPSLOCK是否处于打开状态
if(打开)
PostMessage( nMsg.hwnd, WM_CHAR, 0X41,....);
else
PostMessage( nMsg.hwnd, WM_CHAR, 0X61,....);
}
}
BOOL Ellipse(
HDC hdc, // 绘图设备句柄(BeginPaint返回值)
int nLeftRect, //左上角X坐标
int nTopRect, // 左上角Y坐标
int nRightRect, // 右下角X坐标
int nBottomRect // 右下角Y坐标
);
BOOL GetClientRect(
HWND hWnd, // 窗口句柄
LPRECT lpRect // 返回 窗口的边界信息
);
例如:RECT rc = { 0 };
GetClientRect( hWnd, &rc );
BOOL AppendMenu(
HMENU hMenu, //菜单句柄
UINT uFlags, // 菜单项风格
UINT_PTR uIDNewItem, // 菜单项ID或下拉菜单的句柄
LPCTSTR lpNewItem // 菜单项的名称
);
uFlags:
MF_POPUP - 具有这种风格的菜单项,被点击后弹出下拉
菜单,uIDNewItem参数必须填写下拉菜单
的句柄。
MF_SEPARATOR - 具有这种风格的菜单项为分隔线。
MF_STRING - 具有这种风格的菜单项,被点击后发出消息
(WM_COMMAND).
swprintf_s
day06
DWORD CheckMenuItem(
HMENU hmenu, // 菜单句柄
UINT uIDCheckItem, // 菜单项ID或菜单项索引(位置)
UINT uCheck //
);
uCheck:
MF_BYCOMMAND - uIDCheckItem参数填写菜单项ID
MF_BYPOSITION - uIDCheckItem参数填写菜单项索引
MF_CHECKED - 勾选
MF_UNCHECKED - 非勾选
将客户区坐标系下的坐标 转换为 屏幕坐标系下的坐标
BOOL ClientToScreen(
HWND hWnd, // 窗口句柄
LPPOINT lpPoint // [IN/OUT]
输入:客户区坐标系下坐标
输出:屏幕坐标系下的坐标
);
MAKEINTRESOURCE - 将数字形式的资源ID转换为字符串
形式的资源ID
MAKEINTRESOURCE(IDR_MENU1);
CL.EXE
.cpp----------->.obj|
| LINK.EXE
RC.EXE |--------------->.exe
.rc------------->.res |
BOOL DrawIcon(
HDC hDC, // 绘图设备句柄(BeginPaint返回值)
int X, // 水平坐标
int Y, // 垂直坐标
HICON hIcon // 图标句柄
);
//获取鼠标光标位置(屏幕坐标系下)
BOOL GetCursorPos(
LPPOINT lpPoint // 返回鼠标光标位置
);
ScreenToClient - 将屏幕坐标系下的坐标转换为客户区坐标系
下的坐标
//获取窗口边界信息(客户区坐标系下)
GetClientRect
#include "stdafx.h"
HINSTANCE g_hInstance = 0;//接收当前程序实例句柄
//窗口处理函数
LRESULT CALLBACK WndProc( HWND hWnd, UINT nMsg,
WPARAM wParam, LPARAM lParam )
{
switch( nMsg )
{
case WM_DESTROY:
PostQuitMessage( 0 );//能够使GetMessage返回0?
break;
}
return DefWindowProc( hWnd, nMsg, wParam, lParam );
}
//注册窗口类
void Register( LPSTR lpClassName, WNDPROC wndproc )
{
WNDCLASSEX wce = { 0 };
wce.cbSize = sizeof( wce );
wce.cbClsExtra = 0;
wce.cbWndExtra = 0;
wce.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wce.hCursor = NULL;
wce.hIcon = NULL;
wce.hIconSm = NULL;
wce.hInstance = g_hInstance;
wce.lpfnWndProc = wndproc;
wce.lpszClassName = lpClassName;
wce.lpszMenuName = NULL;
wce.style = CS_HREDRAW | CS_VREDRAW;
RegisterClassEx( &wce );
}
//创建主窗口
HWND CreateMain( LPSTR lpClassName, LPSTR lpWndName )
{
HWND hWnd = CreateWindowEx( 0, lpClassName, lpWndName,
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, NULL, NULL, g_hInstance,
NULL );
return hWnd;
}
//显示窗口
void Display( HWND hWnd )
{
ShowWindow( hWnd, SW_SHOW );
UpdateWindow( hWnd );
}
//消息循环
void Message( )
{
MSG uMsg = { 0 };
while( GetMessage(&uMsg, NULL, 0, 0) )
{
TranslateMessage( &uMsg );
DispatchMessage( &uMsg );
}
}
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
g_hInstance = hInstance;
Register( "Main", WndProc );
HWND hWnd = CreateMain( "Main", "window" );
Display( hWnd );
Message( );
return 0;
}
day07
TranslateAccelerator( hWnd, hAccel, &nMsg )
{
if( nMsg.message != WM_KEYDOWN....)
return 0;
根据nMsg.wParam(虚拟键码值)可以获知 哪个按键被按下
(CTRL + Y)
拿着CTRL + Y到hAccel(加速键表)中匹配查找
if( 没找到 )
return 0;
if( 找到 )
{
PostMessage( nMsg.hwnd, WM_COMMAND,
ID_NEW|||1, NULL );
return 13245;
}
}
HDC hdc = BeginPaint( hWnd,...);
TextOut( hdc, 100, 100, "hello", 5 );
Ellipse( hdc, 100, 100, 300, 300 );
//移动窗口的当前点到它指定的点,并将它指定的点作为窗口当前点。
BOOL MoveToEx(
HDC hdc, // DC句柄
int X, // 指定点的x坐标
int Y, // 指定点的y坐标
LPPOINT lpPoint // 原来的坐标,可以为NULL
);
//从窗口的当前点到它指定的点绘制一条直线
//将它指定的点 做为 窗口的当前点
BOOL LineTo(
HDC hdc, // DC句柄
int nXEnd, // 指定点的x坐标
int nYEnd // 指定点的y坐标
);
//绘制矩形
BOOL Rectangle(
HDC hdc, // DC句柄
int nLeftRect, // 左上角X坐标
int nTopRect, // 左上角Y坐标
int nRightRect, // 右下角X坐标
int nBottomRect // 右下角Y坐标
);
//绘制圆角矩形
BOOL RoundRect(
HDC hdc, // DC句柄
int nLeftRect, // 左上角X坐标
int nTopRect, // 左上角Y坐标
int nRightRect, // 右下角X坐标
int nBottomRect, // 右下角Y坐标
int nWidth, //弧度的宽
int nHeight // 弧度的高
);
//绘制圆形
BOOL Ellipse(
HDC hdc, // DC句柄
int nLeftRect, // 左上角X坐标
int nTopRect, // 左上角Y坐标
int nRightRect, // 右下角X坐标
int nBottomRect // 右下角Y坐标
);
//绘制弧线
BOOL Arc(
HDC hdc, // DC句柄
int nLeftRect, // 左上角X坐标
int nTopRect, // 左上角Y坐标
int nRightRect, // 右下角X坐标
int nBottomRect, // 右下角Y坐标
int nXStartArc, // 起点X坐标
int nYStartArc, // 起点Y坐标
int nXEndArc, // 终点X坐标
int nYEndArc // 终点Y坐标
);
HBRUSH CreatePatternBrush(
HBITMAP hbmp // 位图句柄
);
HBITMAP LoadBitmap(
HINSTANCE hInstance, // handle to application instance
LPCTSTR lpBitmapName // name of bitmap resource
);
day08
复习
一、绘图基础
1.设备上下文
2.图形设备接口(GDI/GDI+)
二、颜色空间
1.计算机三元色:红、绿、蓝
0 - 255
2.颜色深度:位/像素
3.颜色类型:COLORREF - DWORD - unsigned int
0x00BBGGRR
RGB (R, G, B)
GetRValue/GetGValue/GetBValue
三、点
17寸显示器、1024X768分辨率、4:3屏幕
像素宽度=1725.44/5/1024 = 0.337(mm)
像素高度=1725.43/5/768 = 0.337(mm)
COLORREF SetPixel (HDC hdc, int x, int y, COLORREF cr);
COLORREF GetPixel (HDC hdc, int x, int y);
四、直线
BOOL MoveToEx (HDC hdc, int x, int y, LPPOINT pt);
BOOL LineTo (HDC hdc, int x, int y);
五、椭圆弧
BOOL Arc (
HDC hdc,
int left,
int top,
int right,
int bottom,
int xStart,
int yStart,
int xEnd,
int yEnd);
int SetArcDirection (HDC hdc, int ArcDirection);
AD_CLOCKWISE
AD_COUNTERCLOCKWISE
六、封闭图形
1.矩形
BOOL Rectangle (
HDC hdc,
int nLeft,
int nTop,
int nRight,
int nBottom);
2.椭圆
BOOL Ellipse (
HDC hdc,
int nLeft,
int nTop,
int nRight,
int nBottom);
3.圆角矩形
BOOL RoundRect (
HDC hdc,
int nLeft,
int nTop,
int nRight,
int nBottom,
int nWidth,
int nHeight);
七、画笔
线型、线宽、颜色
HPEN CreatePen (int style, int width, COLORREF cr);
HGDIOBJ SelectObject (HDC hdc, HGDIOBJ hgdiobj);
BOOL DeleteObject (HGDIOBJ hgdiobj);
建进用出删
八、画刷
HBRUSH CreateSolidBrush (COLORREF cr);
HBRUSH CreateHatchBrush (int style, COLORREF cr);
HBRUSH CreatePatternBrush (HBITMAP hbmp);
九、库存对象
HGDIOBJ GetStockObject (int object);
object取值:
HOLLOW_BRUSH \ 空画刷,不填充
NULL_BRUSH /
BLACK_BRUSH
WHITE_BRUSH
NULL_PEN - 空画笔,不勾边
BALCK_PEN
WHITE_PEN
...
十、位图
1.基本知识
计算图像分为:
光栅图像:记录图像中每一个像素点的颜色和透明度。
矢量图像:记录图像的渲染算法、绘制指令等信息。
Windows中的位图(Bitmap)是一种光栅图像,通过句柄
HBITMP标识。
2.使用位图
1)添加位图资源
2)从资源中载入位图
HBITMAP LoadBitmap (
HINSTANCE hInstance, // 应用程序实例句柄
LPCTSTR lpBitmapName // 位图资源名
);
成功返回位图句柄,失败返回NULL。
3)创建和当前设备上下文匹配的内存设备上下文
HDC CreateCompatibleDC (
HDC hdc // 当前设备上下文句柄
// NULL表示屏幕设备上下文
);
成功返回与参数设备上下文相匹配的内存设备上下文句柄,失败
返回NULL。
4)将位图选入内存设备上下文
HGDIOBJ hbmpOld = SelectObject (hdcMem,
hbmpNew);
5)从内存设备上下文成像到当前设备上下文
A.原比例成像
BOOL BitBlt (
HDC hdcDest, // 目标设备上下文
int nXDest, // 目标图像左
int nYDest, // 上角坐标
int nWidth, // 图像宽度
int nHeight, // 和高度
HDC hdcSrc, // 源设备上下文
int nXSrc, // 源图像左
int nYSrc, // 上角坐标
DWORD dwRop // 光栅操作(ROP)码
);
B.缩放成像
BOOL StretchBlt (
HDC hdcDest, // 目标设备上下文
int nXDest, // 目标图像左
int nYDest, // 上角坐标
int nWidthDest, // 目标图像宽度
int nHeightDest, // 和高度
HDC hdcSrc, // 源设备上下文
int nXSrc, // 源图像左
int nYSrc, // 上角坐标
int nWidthSrc, // 源图像宽度
int nHeightSrc, // 和高度
DWORD dwRop // 光栅操作(ROP)码
);
6)恢复原位图
SelectObject (hdcMem, hbmpOld);
7)释放位图
DeleteObject (hbmpNew);
8)释放内存设备上下文
DeleteDC (hdcMem);
0 & X = 0 B & C = B
0 | X = X B | C = C
1 & X = X W & C = C
1 | X = 1 W | C = W
十一、坐标映射
1.坐标系
1)设备坐标系:以像素为单位,X向右,Y向下
A.屏幕坐标系:以屏幕左上角为原点
B.窗口坐标系:以窗口左上角为原点
C.客户区坐标系:以客户区左上角为原点
2)逻辑坐标系:坐标单位、轴向和原点可以人为设定。
设备坐标系是缺省坐标系。
1/1440英寸
2.映射模式
int SetMapMode (
HDC hdc, // 设备上下文
int fnMapMode // 映射模式
);
成功返回原来的映射模式,失败返回0。
fnMapMode的取值:
MM_TEXT,文本模式,1逻辑=1设备,原点左上角,X向右,
Y向下,默认模式。
MM_LOENGLISH,低英制,1逻辑=0.01英寸,原点左上角,
X向右,Y向上。
MM_HIENGLISH,高英制,1逻辑=0.001英寸,原点左上角,
X向右,Y向上。
MM_LOMETRIC,低公制,1逻辑=0.1毫米,原点左上角,
X向右,Y向上。
MM_HIMETRIC,高公制,1逻辑=0.01毫米,原点左上角,
X向右,Y向上。
MM_TWIPS,打印,1逻辑=1/1440英寸,原点左上角,
X向右,Y向上。
MM_ANISOTROPIC,各向异性,水平和垂直方向的逻设比可
以独立设置,原点和轴向可以自由定义。
逻设比为正,X向右,Y向下。
逻设比为负,X向左,Y向上。
X: 1逻辑=5设备,X轴向右
Y: 1逻辑=-10设备,Y轴向上
MM_ISOTROPIC,各向同性,水平和垂直方向的逻设以二者大
的为准。
X: 1逻辑=5设备
Y: 1逻辑=-10设备 -> 1逻辑=-5设备
BOOL SetViewportExtEx (
HDC hdc, // 设备上下文
int nXExtent, // 设备单位X范围
int nYExtent, // 设备单位Y范围
LPSIZE lpSize // 原视口范围(可NULL)
);
BOOL SetWindowExtEx (
HDC hdc, // 设备上下文
int nXExtent, // 逻辑单位X范围
int nYExtent, // 逻辑单位Y范围
LPSIZE lpSize // 原窗口范围(可NULL)
);
SetWindowExtEx (hdc, 1, 1, NULL);
SetViewportExtEx (hdc, 2, 3, NULL);
SetWindowExtEx (hdc, 1000, 1000, NULL);
SetViewportExtEx (hdc, 2000, 3000, NULL);
十二、文字
1.绘制单行文字
BOOL TextOut (
HDC hdc, // 设备上下文
int nXStart, // 文本行包络矩形左上角
int nYStart, // 的坐标
LPCTSTR lpString, // 文本字符串首地址
int cbString // 文本字符串长度(以字符为单位)
);
成功返回TRUE,失败返回FALSE。
2.在矩形区域中显示文字
int DrawText (
HDC hdc, // 设备上下文
LPCTSTR lpString, // 文本字符串首地址
int nCount, // 文本字符串长度(可以取-1,字符串必须以空
// 字符结尾)
LPRECT lpRect, // 矩形区域
UINT uFormat // 格式
);
uFormat取值:
DT_LEFT - 靠左
DT_CENTER - 水平居中
DT_RIGHT - 靠右
DT_TOP - 靠上
DT_VCENTER - 垂直居中(仅对单行文本有效)
DT_BOTTOM - 靠下(仅对单行文本有效)
DT_SINGLELINE - 单行
DT_WORDBREAK - 按单词折行
DT_WORD_ELLIPSIS - 显示不下的内容用省略号表示
DT_NOCLIP - 超出矩形区域的部分不做裁剪
DT_NOPREFIX - 对“&”不做转义
&A -> &A
3.设置字符间距
BOOL ExtTextOut (
HDC hdc, // 设备上下文
int x, // 文本行位置
int y, // 坐标
UINT fuOptions, // 输出选项
CONST RECT* lprc, // 裁剪矩形
LPCTSTR lpString, // 文本字符串首地址
UINT cbCount, // 文本字符串长度
CONST INT* lpDx // 字符间距表
);
成功返回TRUE,失败返回FALSE。
4.文字的背景和颜色
int SetBkMode (HDC hdc, int iBkMode);
iBkMode: TRANSPARENT(透明)/OPAQUE(不透明)
COLORREF SetBkColor (HDC hdc, COLORREF cr);
COLORREF SetTextColor (HDC hdc, COLORREF cr);
十三、字体
1.TrueType字体
字体名是系统中对特定字体的唯一标识。
字体句柄HFONT是程序中对字体对象的唯一标识。
2.创建字体
HFONT CreateFont (...);
day09
一、字体的使用
1.创建字体
HFONT CreateFont (
int nHeight, // 字体高度 \ 指定一个即可
int nWidth, // 字体宽度 / 系统自动计算另一个
int nEscapment, // 倾斜角度
int nOrientation, // 旋转角度,大多数字体不支持,置0
int fnWeight, // 字体粗细,细<400<粗
DWORD fdwItalic, // 是否斜体
DWORD fdwUnderline, // 是否带下划线
DWORD fdwStrikeOut, // 是否带删除线
DWORD fdwCharSet, // 字符集,GB2312_CHARSET
DWORD fdwOutputPrecision, // 输出精度,置0
DWORD fdwClipPrecision, // 裁剪精度,置0
DWORD fdwQuality, // 输出质量,置0
DWORD fdwPitchAndFamily, // 匹配字体,若指定字体不
// 存在,则用此参数
LPCTSTR lpszFace // 字体名
);
成功返回字体句柄,失败返回NULL。
2.应用字体
HFONT hfntOld = SelectObject (hdc, hfntNew);
3.绘制文字
TextOut/DrawText/ExtTextOutEx
4.恢复字体
SelectObject (hdc, hfntOld);
5.删除字体
DeleteObject (hfntNew);
二、对话框
1.对话框分类
A.模式对话框:当模式对话框显示时,同进程的其它窗口无法与
用户交互。如字体对话框。
B.无模式对话框:当无模式对话框显示时,同进程的其它窗口可
以与用户交互。如查找对话框。
2.对话框的使用
1)对话框的窗口过程函数
BOOL CALLBACK DialogProc (
HWND hDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam);
返回TRUE:表示自定义窗口过程函数已经处理了此消息,缺省
窗口过程函数无需再处理此消息。
返回FALSE:表示自定义窗口过程函数没有处理了此消息,缺省
窗口过程函数需要处理此消息。
普通窗口过程函数:
LRESULT CALLBACK WindowProc (HWND hWnd,
UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_PAINT:
...
return 0;
case WM_DESTROY:
...
return 0;
}
return DefWindowProc (hWnd, uMsg, wParam, lParam);
}
对话框窗口过程函数:
LRESULT CALLBACK DefDlgProc (HWND hDlg,
UINT uMsg, WPARAM wParam, LPARAM lParam) {
// 函数指针pfuncDialogProc指向自定义对话框窗口过程函数
if (pfuncDialogProc (hDlg, uMsg, wParam, lParam))
return 0;
switch (uMsg) {
...
}
}
DefDlgProc:系统预定义,与对话框窗口类一起注册到系统中。
DialogProc:程序员自己定义,通过函数指针交给系统,使之
可被DefDlgProc调用。
3.模式对话框
1)创建
int DialogBox (
HINSTANCE hInstance, // 应用程序实例句柄
LPCTSTR lpTemplate, // 对话框模板资源名
HWND hWndParent, // 父窗口句柄
DLGPROC lpDialogFunc // 自定义对话框窗口过程函数指针
);
成功返回传给EndDialog函数的nResult参数,失败返回-1。
需要添加对话框资源。
阻塞函数,直到对话框被关闭才会返回,继续执行后面的代码。
模式对话框自己拥有独立的消息循环,但对话框显示的时候,主
消息循环会被挂起,对话框自己的消息循环接管对消息的处理。
2)销毁
BOOL EndDialog (
HWND hDlg, // 对话框句柄
int nResult // DialogBox函数的返回值
);
成功返回TRUE,失败返回FALSE。
EndDialog除了销毁对话框以外,还要恢复主消息循环。
DestroyWindow只负责销毁窗口,不管消息循环。
3)消息
没有WM_CREATE消息,代之以WM_INITDIALOG消息。
4.无模式对话框
1)创建
HWND CreateDialog (
HINSTANCE hInstance, // 应用程序实例句柄
LPCTSTR lpTemplate, // 对话框模板资源名
HWND hWndParent, // 父窗口句柄
DLGPROC lpDialogFunc // 自定义对话框窗口过程函数指针
);
成功返回对话框句柄,失败返回NULL。
非阻塞函数,创建成功即返回对话框句柄。
需要调用ShowWindow函数显示对话框。
无模式对话框没有自己的消息循环,和主窗口共用同一个消息
循环,和模式对话框相比,更像一个普通的子窗口。
2)销毁
BOOL DestroyWindow (HWND hWnd);
成功返回TRUE,失败返回FALSE。
3)消息
没有WM_CREATE消息,代之以WM_INITDIALOG消息。
三、控件
1.基本概念
1)系统预定义的窗口类。如按钮、编辑框等等。
基本控件:按钮、编辑框、静态框、列表框、组合框、滚动条。
扩展控件:列表视图,树状视图,滑动游标,进度条,工具栏,
状态栏,属性页,等等。
2)无需注册,直接给出窗口类名,用CreateWindow/
CreateWindowEx函数创建。
3)作为子窗口的每个控件都有一个唯一标识——控件ID。
4)程序和控件消息交互。
A.窗口消息:由程序通过SendMessage()向控件发送的消息。
设置/获取控件的状态。
B.通知消息:由控件发送给父窗口的消息。用于表示控件中发生
的事件。
2.静态框
1)显示文字、图标、位图等。
2)窗口类名:STATIC
3)风格
SS_ICON - 图标
SS_BITMAP - 位图
SS_BLACKFRAME - 黑框
SS_BLACKRECT - 黑块
SS_GRAYFRAME - 灰框
SS_GRAYRECT - 灰块
SS_LEFT - 文字靠左
SS_CENTER - 文字居中
SS_CENTERIMAGE - 图标/位图居中
SS_NOPREFIX - 不转义&
SS_NOTIFY - 可以发送通知消息
4)创建
CreateWindow/CreateWindowEx
CreateWindow ("STATIC", "Hello", ...);
CreateWindow ("STATIC", "#101", ...);
控件ID通过菜单句柄参数传入。
5)窗口消息
STM_SETICON - 设置图标
wParam - 图标句柄
lParam - 0
STM_SETIMAGE - 设置图像
wParam - 图像类型IMAGE_ICON/IMAGE_BITMP/IMAGE_CURSOR
lParam - 图像句柄
day10
一、按钮
1.风格
1)下压按钮:BS_PUSHBUTTON、BS_DEFPUSHBUTTON
2)分组框:BS_GROUPBOX
3)复选框:BS_CHECKBOX(手动)
BS_AUTOCHECKBOX(自动)
BS_3STATE(手动三态)
BS_AUTO3STATE(自动三态)
4)单选框:BS_RADIOBUTTON(手动)
BS_AUTORADIOBUTTON(自动)
2.类名:BUTTON
3.通知消息:BN_CLICKED
4.窗口消息
BM_SETCHECK - 设置选择状态
wParam - BST_CHECKED(勾)
BST_INDETERMINATE(灰)
BST_UNCHECKED(无)
lParam - 0
BM_GETCHECK - 获取选择状态,SendMessage返回
BST_CHECKED(勾)
BST_INDETERMINATE(灰)
BST_UNCHECKED(无)
wParam - 0
lParam - 0
6.组风格 —— WS_GROUP
WS_GROUP风格用于为单选框控件分组。从一个具有
WS_GROUP风格的单选框到下一个具有WS_GROUP风格的单
选框之前的控件为一组。组内互斥,组间独立。
二、编辑框
1.分类
单行编辑框:只能编辑一行文字。
多行编辑框:可以编辑多行文字。
2.类名:EDIT
3.风格
ES_AUTOHSCROLL - 水平自动滚动
ES_AUTOVSCROLL - 垂直自动滚动
ES_LEFT - 文字靠左
ES_CENTER - 文字居中
ES_RIGHT - 文字靠右
ES_MULILINE - 多行
ES_NUMBER - 只能输入0-9
ES_PASSWORD - 密码
ES_READONLY - 只读
三、滚动条
1.分类
1)水平滚动条
2)垂直滚动条
2.类名:SCROLLBAR
3.风格:SBS_VERT/SBS_HORZ
4.窗口消息
SBM_SETRANGE - 设置滚动范围
wParam - 最小位置
lParam - 最大位置
SBM_GETRANGE - 获取滚动范围
wParam - 最小位置指针
lParam - 最大位置指针
SBM_SETPOS - 设置滚动位置
wParam - 滚动位置
lParam - 是否重绘滚动条,TRUE/FALSE
SBM_GETPOS - 获取滚动位置,通过SendMessage返回
wParam - 0
lParam - 0
5.通知消息
WM_HSCROLL - 水平滚动
WM_VSCROLL - 垂直滚动
wParam - LOWORD,滚动码,HIWORD,当前位置(仅对
SB_THUMBTRACK/SB_THUMBPOSITION滚动
码有效)
lParam - 滚动条控件句柄
滚动码:
SB_LINELEFT - 点左箭头
SB_LINERIGHT - 点右箭头
SB_PAGELEFT - 点左空白
SB_PAGERIGHT - 点右空白
SB_LINEUP - 点上箭头
SB_LINEDOWN - 点下箭头
SB_PAGEUP - 点上空白
SB_PAGEDOWN - 点下空白
SB_THUMBTRACK - 拖动滑块
SB_THUMBPOSITION - 释放滑块
四、组合框
1.分类
简单组合框
下拉组合框
下拉列表组合框
2.风格
CBS_SIMPLE
CBS_DROPDOWN
CBS_DROPDOWNLIST
3.类名:COMBOBOX
4.添加选项
CB_ADDSTRING - 追加
wParam - 0
lParam - 字符串指针
CB_INSERTSTRING - 插入
wParam - 插入位置,在此项之前查,从0开始
lParam - 字符串指针
4.删除选项
CB_DELETESTRING - 删除指定选项
wParam - 选项索引
lParam - 0
CB_RESETCONTENT - 清空
wParam - 0
lParam - 0
5.获取/设置当前选项
CB_GETCURSEL - 获取当前选项,SendMessage返回当前选项
的索引,无选项目返回CB_ERR(-1)。
wParam - 0
lParam - 0
CB_SETCURSEL - 设置当前选项
wParam - 选项索引
lParam - 0
6.查找
CB_FINDSTRING - 查找第一个匹配字符串,模糊匹配,
SendMessage返回匹配项的索引,找不到返回CB_ERR。
wParam - 查找起点(查找范围中第一项的前一项的索引)
lParam - 匹配字符串指针
CB_FINDSTRINGEXACT - 查找第一个匹配字符串,精确匹配,
SendMessage返回匹配项的索引,找不到返回CB_ERR。
wParam - 查找起点(查找范围中第一项的前一项的索引)
lParam - 匹配字符串指针
CB_SELECTSTRING - 模糊匹配式的查找,如果找到了,
自动选中匹配项
wParam - 查找起点(查找范围中第一项的前一项的索引)
lParam - 匹配字符串指针
7.获取选项的内容
CB_GETLBTEXTLEN - 获取选项字符串的长度,
SendMessage返回选项字符串的字符个数,不含结尾空字符。
失败返回CB_ERR。
wParam - 选项索引
lParam - 0
CB_GETLBTEXT - 获取选项字符串,自动追加结尾空字符
wParam - 选项索引
lParam - 缓冲区指针
8.目录
CB_DIR - 显示文件和目录
wParam - 包含哪些类型的文件
lParam - 路径
wParam取值:
DDL_ARCHIVE - 普通文件
DDL_DIRECTORY - 目录(带[]显示)
DDL_DRIVES - 驱动文件
DDL_HIDDEN - 隐藏文件
DDL_SYSTEM - 系统文件(.sys)
DDL_READONLY - 只读文件
DDL_READWRITE - 可读可写文件
DDL_EXCLUSIVE - 排它,只包含以上属性
无此,还包含以上属性
day11
一、库
1.静态库
2.动态库
3.静态加载动态库
直接链接动态库的导入库。
4.动态加载动态库
HMODULE LoadLibrary (
LPCTSTR lpFileName // 库路径,如果只给文件名,
// 根据PATH环境变量搜索
);
成功返回动态库的句柄,失败返回NULL。
FARPROC GetProcAddress (
HMODULE hModule, // 动态库句柄
LPCSTR lpProcName // 函数名(C++换名后的函数名)
);
成功返回函数地址,失败返回NULL。
BOOL FreeLibrary (
HMODULE hModule // 动态库句柄
);
成功返回TRUE,失败返回FALSE。
5.动态库的入口
BOOL WINAPI DllMain (
HANDLE hinstDll, // 动态库实例句柄
DWORD dwReason, // 被调用原因
LPVOID lpvReserved // 保留
);
dwReason取值:
DLL_PROCESS_ATTACH - 进程加载,其实就是被主线程加载
DLL_PROCESS_DETACH - 进程卸载,其实就是被主线程卸载
DLL_THREAD_ATTACH - 线程加载,其实就是被子线程加载
DLL_THREAD_DETACH - 线程卸载,其实就是被子线程卸载
返回TRUE表示动态库加载成功,返回FALSE表示加载失败。
二、文件系统
1.获取磁盘驱动器信息
DWORD WINAPI GetLogicalDrives (void);
返回值从低位到高位依次表示A、B、C...
0无此驱动器
1有此驱动器
2.获取系统驱动器
DWORD WINAPI GetLogicalDriveStrings (
DWORD nBufferLength, // 缓冲区长度
LPTSTR lpBuffer // 缓冲区地址
);
成功返回字符串长度,失败返回0。
3.获取当前目录
DWORD GetCurrentDirectory (
DWORD nBufferLength, // 缓冲区长度
LPTSTR lpBuffer // 缓冲区地址
);
成功返回字符串长度,失败返回0。
4.设置当前目录
BOOL SetCurrentDirectory (
LPCTSTR lpPathName // 期望当前目录路径
);
成功返回TRUE,失败返回FALSE。
5.获取WINDOWS目录
UINT GetWindowsDirectory (
LPTSTR lpBuffer, // 缓冲区地址
DWORD nBufferLength // 缓冲区长度
);
成功返回字符串长度,失败返回0。
6.获取系统目录
UINT GetSystemDirectory (
LPTSTR lpBuffer, // 缓冲区地址
DWORD nBufferLength // 缓冲区长度
);
成功返回字符串长度,失败返回0。
7.获取临时目录
DWORD GetTempPath (
DWORD nBufferLength, // 缓冲区长度
LPTSTR lpBuffer // 缓冲区地址
);
成功返回字符串长度,失败返回0。
8.创建目录
BOOL CreateDirectory (
LPCTSTR lpPathName, // 目录路径
LPSECURITY_ATTRIBUTES lpsa // 安全属性,置NULL
);
成功返回TRUE,失败返回FALSE。
9.移动文件/目录
BOOL MoveFile (
LPCTSTR lpExistingFileName, // 原路径
LPCTSTR lpNewFileName // 新路径
);
成功返回TRUE,失败返回FALSE。
10.删除空目录
BOOL RemoveDirectory (
LPCTSTR lpPathName // 欲删除的目录路径
);
成功返回TRUE,失败返回FALSE。
11.创建/打开文件
HANDLE CreateFile (
LPCTSTR lpFileName, // 文件路径
DWORD dwDesiredAccess, // 访问方式
DWORD dwShareMode, // 共享方式
LPSECURITY_ATTRIBUTES lpsa, // 安全属性,置NULL
DWORD dwCreationDisposition, 创建/打开方式
DWORD dwFlagsAndAttributes, // 文件属性
HANDLE hTemplateFile // 文件句柄模板,磁盘文件置NULL
// 打印机同步或异步传输
);
成功返回文件句柄,失败返回INVALID_HANDLE_VALUE(-1).
dwDesiredAccess取值:
0 - 质询(判断文件是否存在)
GENERIC_READ - 读取
GENERIC_WRITE - 写入
dwShareMode取值:
FILE_SHARE_DELETE - 允许其它进程删除
FILE_SHARE_READ - 允许其它进程读取
FILE_SHARE_WRITE - 允许其它进程写入
dwCreationDisposition取值:
CREATE_NEW - 不存在就创建,已存在就失败
CREATE_ALWAYS - 不存在就创建,已存在就删除原文件再创建
OPEN_EXISTING - 已存在就打开,不存在就失败
OPEN_ALWAYS - 已存在就打开,不存在就创建新文件在打开
TRUNCATE_EXISTING - 已存在就先清空在打开,不存在就失败
12.写文件
BOOL WriteFile (
HANDLE hFile, // 文件句柄
LPCVOID lpBuffer, // 数据缓冲区
DWORD nNumberOfBytesToWrite, // 期望写入字节数
LPDWORD lpNumberOfBytesWritten, // 实际写入字节数
// 可置NULL
LPOVERLAPPED lpOverlapped // 同步传输置NULL
);
成功返回TRUE,失败返回FALSE。
13.读文件
BOOL ReadFile (
HANDLE hFile, // 文件句柄
LPCVOID lpBuffer, // 数据缓冲区
DWORD nNumberOfBytesToRead, // 期望读取字节数
LPDWORD lpNumberOfBytesRead, // 实际读取字节数
// 可置NULL
LPOVERLAPPED lpOverlapped // 同步传输置NULL
);
成功返回TRUE,失败返回FALSE。
day12
一、库
1.静态库和动态库的区别
1)机制
2)运行
3)性能:时间、空间
4)部署
2.构建和使用库
导出声明:__declspec (dllexport)
导入声明:__declspec (dllimport)
#ifdef XXX_EXPORTS
#define XXX_API __declspec (dllexport)
#else
#define XXX_API __declspec (dllimport)
#endif
动态库的导入库:.lib
3.动态加载动态库
LoadLibrary
GetProcAddress
FreeLibrary
4.入口函数:DllMain
二、目录
GetLogicalDrives,获取逻辑驱动器掩码
GetLogicalDriveStrings,获取逻辑驱动器字符串表
C:_D:_E:__
GetCurrentDirectory
SetCurrrentDirectory
GetWindowsDirectory
GetSystemDirectory
GetTempPath
CreateDirectory
MoveFile,不能跨驱动器
三、文件
CreateFile
CloseHandle
WriteFile
ReadFile
BOOL SetFilePointerEx (
HANDLE hFile, // 文件句柄
LARGE_INTEGER liDistanceToMove, // 偏移字节
PLARGE_INTEGER lpNewFilePointer, // 文件指针
DWORD dwMoveMethod // 偏移起点
);
dwMoveMethod取值:
FILE_BEGIN - 从文件头开始偏移
FILE_CURRENT - 从当前位置开始偏移
FILE_END - 从文件尾开始偏移
DWORD SetFilePointer (
HANDLE hFile, // 文件句柄
LONG lDistanceToMove, // 偏移字节数的低32位
PLONG lpDistanceToMoveHigh, // 输入,偏移字节数的高32位
// 输出,文件位置的高32位
DWORD dwMoveMethod // 偏移起点
);
返回文件位置的低32位。
BOOL CopyFile (
LPCTSTR lpExistingFileName, // 源路径
LPCTSTR lpNewFileName, // 新路径
BOOL bFailIfExists // TRUE,目标存在即失败
// FALSE,目标存在即覆盖
);
成功返回TRUE,失败返回FALSE。
BOOL MoveFile (
LPCTSTR lpExistingFileName, // 源路径
LPCTSTR lpNewFileName, // 新路径
);
成功返回TRUE,失败返回FALSE。
移动目录不能跨驱动器,但是移动文件可以跨驱动器。
BOOL DeleteFile (LPCTSTR lpFileName);
BOOL SetFileAttributes (
LPCTSTR lpFileName, // 目录/文件路径
DWORD dwFileAttributes // 目录/文件属性
);
成功返回TRUE,失败返回FALSE。
DWORD GetFileAttributes (
LPCTSTR lpFileName // 目录/文件路径
);
成功返回文件属性,失败返回-1。
HANDLE FindFirstFile (
LPCTSTR lpFileName, // 查找路径
LPWIN32_FIND_DATA lpFindFileData // 查找信息
);
成功返回查找句柄,用于后续的继续查找。
失败返回INVALID_HANDLE_VALUE。
BOOL FindNextFile (
HANDLE hFindFile, // 查找句柄,来自FindFirstFile返回
LPWIN32_FIND_DATA lpFindFileData // 查找信息
);
成功返回TRUE,失败返回FALSE。
找完了,GetLastError()返回ERROR_NO_MORE_FILE。
四、内存
1.地址空间
32为系统的地址空间:4G
用户空间:0 ~ 2G-1
内核空间:2G ~ 4G-1
------------------- 4G
内核地址空间
------------------- 2G
禁入区
------------------- 0x7FFF0000
用户区
------------------- 64K
空指针区
------------------- 0
2.物理内存
半导体内存+磁盘分页文件
3.内存映射表
以页(4K)为单位做内存映射。
4.虚拟内存管理函数
1)分配虚拟内存
LPVOID VirtualAlloc (
LPVOID lpAddress, // NULL或提交地址
SIZE dwSize, // 内存大小(字节)
DWORD flAllocationType, // 分配方式
DWORD flProtect // 访问方式
);
flAllocationType取值:
MEM_COMMIT - 获得地址空间的同时提交到物理内存
MEM_RESERVE - 只获得地址空间,不提交到物理内存
2)获取内存状态
void GlobalMemoryStatus (
LPMEMORYSTATUS lpBuffer // 内存状态信息
);
struct MEMORYSTATUS {
DWORD dwLength; // 结构体字节数
DWORD dwMemoryLoad; // 内存使用率
SIZE_T dwTotoalPhys; // 物理内存总字节数
SIZE_T dwAvaiPhys; // 空闲物理内存字节数
SIZE_T dwTotalPageFile; // 分页文件总字节数
SIZE_T dwAvailPageFile; // 空闲分页文件字节数
SIZE_T dwTotalVirtual; // 虚拟内存总字节数
SIZE_T dwAvailVirtual; // 空闲虚拟内存字节数
};
3)释放虚拟内存
BOOL VirtualFree (
LPVOID lpAddress, // 虚拟内存地址
SIZE_T dwSize, // 释放字节数,0表示全部释放
DWORD dwFreeType // 释放方式
);
成功返回TRUE,失败返回FALSE。
dwFreeType取值:
MEM_DECOMMIT - 只解除与物理内存的映射,不释放地址空间
MEM_RELEASE - 既解除与物理内存的映射,同时释放地址空间
dwSize必须取0。
5.堆内存
1)获取进程的首个堆
HANDLE GetProcessHeap (void);
成功返回调用进程的首个堆的句柄,失败返回NULL。
2)获取进程的所有堆
DWORD GetProcessHeaps (
DWORD NumberOfHeaps, // 堆句柄数组的容量
PHANDLE ProcessHeaps // 堆句柄数组
);
成功返回进程堆的个数,失败返回0。
3)创建堆
HANDLE CreateHeap (
DWORD flOptions, // 创建选项
DWORD dwInitialSize, // 初始字节数
DWORD dwMaximumSize // 最大字节数, 0表示无限大
);
flOptions取值
HEAP_GENERATE_EXCEPTIONS - 在堆中分配内存失败抛出异常
HEAP_NO_SERIALIZE - 支持以不连续的方式使用堆内存
成功返回堆句柄,失败返回NULL。
4)分配堆内存
LPVOID HeapAlloc (
HANDLE hHeap, // 堆句柄
DWORD dwFlags, // 分配方式
DWORD dwBytes // 内存大小(字节)
);
成功返回堆内存地址,失败返回NULL。
dwFlags取值:
HEAP_GENERATE_EXCEPTIONS - 在堆中分配内存失败抛出异常
HEAP_NO_SERIALIZE - 支持以不连续的方式使用堆内存
HEAP_ZERO_MEMORY - 初始化为零
调用HeapCreate函数已经指定了某些创建选项,分配内存时
又指定了存在冲突的分配方式,以创建选项为准。
5)释放堆内存
BOOL HeapFree (
HANDLE hHeap, // 堆句柄
DWORD dwFlags, // 释放方式,只能取HEAP_NO_SERIALIZE
LPVOID lpMem // 堆内存地址
);
成功返回TRUE,失败返回FALSE。
6)销毁堆
BOOL HeapDestroy (
HANDLE hHeap // 堆句柄
);
成功返回TRUE,失败返回FALSE。
当堆被销毁时,其中的所有未被释放的堆内存都会被自动释放。
6.内存映射文件
在一块虚拟内存和一段文件之间建立映射。
1)创建映射
HANDLE CreateFileMapping (
HANDLE hFile, // 文件句柄
LPSECURITY_ATTRIBUTES lpas, // 安全属性,NULL
WORD flProtect, // 访问方式
DWORD dwMaximumSizeHigh, // 映射区间的高
DWORD dwMaximumSizeLow, // 低32位
LPCTSTR lpName // 映射名,NULL表示匿名映射,其它进程
// 无法访问该映射
);
成功返回映射句柄,失败返回NULL。
2)加载映射
LPVOID MapViewOfFile (
HANDE hFileMapping, // 映射句柄
DWORD dwDesireAccess, // 访问方式
DWORD dwFileOffsetHigh, // 文件偏移高32位
DWORD dwFileOffsetLow, // 文件偏移低32位
SIZE_T dwNumberOfBytesToMap // 映射字节数,不能超过
// 映射区间的大小
);
成功返回建立映射的虚拟内存地址,失败返回NULL。
3)卸载映射
BOOL UnmapViewOfFile (
LPCVOID lpBaseAddress // 映射地址
);
成功返回TRUE,失败返回FALSE。
4)销毁映射
BOOL CloseHandle (
HANDE hFileMapping // 映射句柄
);
成功返回TRUE,失败返回FALSE。
5)关闭文件
CloseHandle (hFile);
6)打开映射
HANDLE OpenFileMapping (
DWORD dwDesireAccess, // 访问方式
BOOL hInheritHandle, // 子进程是否可以继承此句柄
LPCTSTR lpName // 映射名
);
成功返回映射句柄,失败返回NULL。
写进程 读进程
创建文件
创建映射 打开映射
加载映射 加载映射
写入数据 读取数据
卸载映射 卸载映射
销毁映射
关闭文件
五、进程
1.进程的基本概念
2.环境变量
LPTCH GetEnvironmentStrings (void);
PATH=C:\WindowsHOME=C:\AdministratorINCLUDE=C:\VC98\Include
注释:”_“代表空字符'\0'。
BOOL FreeEnvironmentStrings (
LPTCH lpszEnvironmentBlock // 环境变量串首地址
);
成功返回TRUE,失败返回FALSE。
day13
一、环境变量
1.获取所有的环境变量
GetEnvironmentStrings
FreeEnvironmentStrings
2.设置环境变量
BOOL SetEnvironmentVariable (
LPCTSTR lpName, // 变量名
LPCTSTR lpValue // 变量值
);
成功返回TRUE,失败返回FALSE。
3.获取特定的环境变量
DWORD GetEnvironmentVariable (
LPCTSTR lpName, // 变量名
LPTSTR lpBuffer, // 变量值缓冲区
DWORD nSize // 变量值缓冲区大小
);
成功返回变量值长度,失败返回0。
二、进程信息
1.进程标识(PID)
DWORD GetCurrentProcessId (void);
2.进程句柄
HANDLE GetCurrentProcess (void);
三、创建进程
1.WinExec
2.ShellExecute
3.BOOL WINAPI CreateProcess (
LPCTSTR lpApplicationName, // 可执行程序路径
LPTSTR lpCommandLine, // 命令行参数
LPSECURITY_ATTRIBUTES lppsa, // 进程安全属性,NULL
LPSECURITY_ATTRIBUTES lptsa, // 线程安全属性,NULL
BOOL bInheritHandles, // 子进程是否继承父进程的句柄
DWORD dwCreationFlags, // 创建标志,0立即启动
LPVOID lpEnvironment, // 子进程环境变量,NULL继承
// 父进程环境
LPCTSTR lpCurrentDirectory, // 子进程的工作目录,NULL
// 继承父进程工作目录
LPSTARTUPINFO psi, // 启动信息
LPPROCESS_INFORMATION ppi // 子进程信息(输出)
);
成功返回TRUE,失败返回FALSE。
四、退出进程
1.从入口函数(main/WinMain)中return。
2.在任意函数中调用标准函数exit。
3.调用Win32函数ExitProcess。
void ExitProcess (
UINT uExitCode // 退出码
);
BOOL GetExitCodeProcess (
HANDLE hProcess, // 进程句柄
LPDWORD lpExitCode // 退出码(输出)
);
五、终止进程
BOOL TerminateProcess (
HANDLE hProcsss, // 进程句柄
UINT uExitCode // 退出码
);
HANDLE OpenProcess (
DWORD dwDesireAccess, // PROCESS_ALL_ACCESS
BOOL hInheritHandle, // 子进程是否可以继承该函数所返回
// 的句柄
DWORD dwProcessId // 进程标识
);
成功返回给定PID进程的句柄,失败返回NULL。
六、关闭进程句柄
CloseHandle
并非关闭进程,只是释放进程描述信息块有关的内存资源。
七、等候进程结束
DWORD WaitForSingleObject (
HANDLE hHandle, // 句柄
DWORD dwMilliseconds // 超时(毫秒),INFINITE无限等待
);
成功返回事件代码,失败返回WAIT_FAILED(-1)。
事件代码:
WAIT_OBJECT_0 - 参数句柄有信号
WAIT_TIMEOUT - 超时了
阻塞,直到所给参数句柄有信号或者超时才会返回。
当进程活动时,其句柄为无信号状态,当进程终止时,
其句柄处于有信号状态。
八、线程
1.基本概念
1)线程是可以执行的代码的实例。系统以线程为单位调度程序。
一个进程中可以包含多个线程,但是必须有一个主线程。
2)线程的特点
A.每个线程都有一个唯一的标识:TID
B.每个线程都有自己的安全属性。
C.每个线程都有自己的内存栈。
D.一个进程的所有线程共享除栈以外的所有内存空间。
int x = 0;
void foo (void) {
for (int i = 0; i < 1000; ++i)
++x;
}
3)线程调度
将CPU的执行时间划分成许多时间片,分配给不同的线程。
操作系统根据时间片的分配,轮流执行不同的线程。
2.线程过程函数
DWORD WINAPI ThreadProc (LPVOID lpParam);
lpParam线程参数来自创建线程的函数。
该函数的返回值将通过GetExitCodeThread()函数返回。
3.创建线程
HANDLE CreateThread (
LPSECURITY_ATTRIBUTES lpsa, // 安全属性,NULL
SIZE_T dwStackSize, //线程栈的初始大小,
// 0表示取调用线程栈的大小
LPTHREAD_START_ROUTINE lpStartAddress,
// 线程过程函数指针
LPVOID lpParam, // 线程过程函数的参数
DWORD dwCreationFlags, // 创建方式,0立即执行
LPDWORD lpThreadId // 线程标识
);
成功返回线程句柄,失败返回NULL。
等待线程的结束:WaitForSingleObject (hThead, ...);
4.挂起线程
DWORD SuspendThread (HANDLE hThread);
成功返回线程此前被挂起的次数。
5.恢复线程
DWORD ResumeThread (HANDLE hThread);
成功返回线程此前被挂起的次数。
1 - 0 0 - 0
2 - 1 1 - 1
3 - 2 2 - 2
6.终止线程
1)主动终止
从线程过程函数中返回:return dwExitCode
VOID ExitThread (DWORD dwExitCode);
BOOL GetExitCodeThread (
HANDLE hThread, // 线程句柄
LPDWORD lpExitCode // 退出码(输出)
);
2)被动终止
BOOL TerminateThread (
HANDLE hThread, // 线程句柄
DWORD dwExitCode // 退出码
);
7.调整线程的优先级
BOOL SetThreadPriority (
HANDLE hThread, // 线程句柄
int nPriority // 优先级
);
nPriority取值:
THREAD_PRIORITY_HIGHEST - 最高
THREAD_PRIORITY_ABOVE_NOMAL - 较高
THREAD_PRIORITY_NOMAL - 普通
THREAD_PRIORITY_BELOW_NOMAL - 较低
THREAD_PRIORITY_LOWEST - 最低
优先级越高的线程获得的时间片越长,
被处理器调度的机会也越多,执行任务越快。
day14
一、线程同步
1.并发冲突
1)原子锁
A.原子自增
LONG InterlockedIncrement (
LPLONG lpAddend // 自增变量地址
);
返回自增后的结果。
B.原子自减
LONG InterlockedDecrement (
LPLONG lpAddend // 自减变量地址
);
2)临界区
CRITICAL_SECTION - 临界区结构
初始化临界区
VOID InitializeCriticalSection (
LPCRITICAL_SECTION lpcs // 临界区对象地址
);
进入临界区
VOID EnterCriticalSection (
LPCRITICAL_SECTION lpcs // 临界区对象地址
);
任何时候都只能有一个线程在临界区内,其它期望进入临界区的
线程都会阻塞在此函数上,直到其中某个线程获得对该临界区的
使用权为止。
离开临界区
VOID LeaveCriticalSection (
LPCRITICAL_SECTION lpcs // 临界区对象地址
);
释放堆参数临界区的所有权,式其它阻塞于
EnterCriticalSection函数上的线程有得到此临界区的机会。
删除临界区
VOID DeleteCriticalSection (
LPCRITICAL_SECTION lpcs // 临界区对象地址
);
3)互斥体
创建互斥体
HANDLE CreateMutex (
LPSECURITY_ATTRIBUTES lpsa, // 安全属性,NULL
BOOL bInitialOwner, // 调用线程是否初始拥有该互斥体
LPCTSTR lpName // 互斥体名,用于进程之间互斥,NULL
// 表示匿名互斥,用于线程
);
成功返回互斥体句柄,失败返回NULL。
等待互斥体
WaitForSingleObject (hMutex, INFINITE);
若其它线程拥有该互斥体,则hMutex无信号,此函数阻塞。
直到调用线程获得对该互斥体的所有权,此时hMutex有信号,
此函数返回WAIT_OBJECT_0。
释放互斥体
BOOL ReleaseMutex (
HANDLE hMutex // 互斥体句柄
);
成功返回TRUE,失败返回FALSE。
一旦调用线程成功释放了互斥体,某个此时正在等待该互斥体的
线程就会立即从WaitForSingleObject函数中返回,同时拥有该
互斥体。任何时候只会有一个线程拥有互斥体。
销毁互斥体
CloseHandle (hMutex);
4)三种解决并发冲突问题的方法
原子锁 临界区 互斥体
线程 线程 线程/进程
自增减和交换 任何任务 任何任务
最快 较慢 更慢
2.资源竞争
被服务者>服务者
信号量,资源计数器
创建信号量
HANDLE CreateSemaphore (
LPSECURITY_ATTRIBUTES lpsa, // 安全属性,NULL
LONG lInitialCout, // 初始资源计数
LONG lMaximemCout, // 最大资源计数
LPCTSTR lpName // 信号量名,跨进程,线程NULL
);
成功返回信号量句柄,失败返回NULL。
等待信号量(够减)
WaitForSingleObject (hSema, INFINITE);
如果hSema所标识的信号量中的资源计数为0(不够减),即
hSema无信号,那么该函数将阻塞。直到资源计数大于0(够减)
时,即hSema有信号,函数返回,同时给资源计数减1。
释放信号量
BOOL ReleaseSemaphore (
HANDLE hSema, // 信号量句柄
LONG lReleaseCount, // 释放资源数
LPLONG lpPrevCount, // 释放前的资源计数(输出),
// 可NULL
);
成功返回TRUE,失败返回FALSE。
关闭信号量
CloseHandle (hSema);
3.并发协作
停——等
创建事件
HANDLE CreateEvent (
LPSECURITY_ATTRIBUTES lpsa, // 安全属性,NULL
BOOL bManualReset, // 是否手动复位
BOOL bInitialState, // 是否初始有信号
LPCTSTR lpName // 事件名,跨进程,线程置NULL
);
成功返回事件句柄,失败返回NULL。
若bManualReset为FALSE,则WaitFor...函数返回即自动复位,
否则必须通过ResetEvent函数对其手动复位。
等待事件
WaitForSingleObject (hEvent, INFINITE);
若无事件发生,则hEvent为无信号状态,此函数阻塞,直到有
事件发生,此时hEvent为有信号状态,函数立即返回。函数返回
以后hEvent是否继续保持有信号状态取决于bManualReset是
TRUE还是FALSE。
触发事件
BOOL SetEvent (
HANDLE hEvent // 事件句柄
);
成功返回TRUE,失败返回FALSE。
复位事件
BOOL ResetEvent (
HANDLE hEvent // 事件句柄
);
成功返回TRUE,失败返回FALSE。
关闭事件
CloseHandle (hEvent);
int a = 100;
void add (void) {
++a;
}
void sub (void) {
--a;
}
add ();
sub ();
4.线程局部存储
局部于线程的全局变量。因为它是全局变量,所以它对所有函数
均可见,但同时它又局部于线程,因此不存在并发冲突,每个线
程只使用属于自己的全局变量。
__declspec (thread)
-----------------------
VC
窗口和消息
基本消息
鼠标键盘
菜单,手动/资源
图标、光标、位图、字符串、加速键、对话框、版本
绘图和GDI对象
对话框和控件
库
文件
内存
进程和线程
打赏
License
本作品由Simon(http://www.uusystem.com)创作,采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。 欢迎转载,但任何转载必须保留完整文章,在显要地方显示此声明以及原文链接。如您有任何疑问或者授权方面的协商,请邮件:postmaster@uusystem.com。