返回介绍

1 C

2 C++

3 Windows

4 Linux

5 数据库

6 数据结构

7 算法

8 Qt

9 AS400

10 Web

12 C

13 框架

14 协议

15 工具

17 QA

3.1.1 Win32_Note

发布于 2023-10-02 20:38:18 字数 113162 浏览 0 评论 0 收藏 0

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对象

对话框和控件

文件

内存

进程和线程

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文