学Windows时候的一篇笔记
来源:互联网 发布:v家调音软件 编辑:程序博客网 时间:2024/04/28 19:39
这也是我的纸质版文档敲出来的,不发上来对不住自己敲键盘敲到手肿的心情....噢噢。
老师:Mr郝 2011--2
Windows课程
Windows编程基础
文字编码
窗口程序
绘图基础
对话框
控件
动态库
Windows内存管理
进程线程
线程同步技术
...
一· Window编程基础
1 Windows应用程序的分类
1.1 DOS程序 - 没有窗口,是在DOS窗口中
执行,不提供用户交互的窗口。
1.2 窗口程序 - 提供一个与用户交互的窗口,
可以接收用户的鼠标和键盘等输入,也可
显示相应的信息和数据。
1.3 库程序 - 提供了执行的代码、变量或者数据。
不是单独执行,包括动态库和静态库
1.4 比较
1.4.1 程序的入口不同
DOS程序:main
窗口程序:WinMain
动态库: DllMain
静态库:无入口
1.4.2 编译链接后的生成文件
DOS程序和窗口程序:EXE文件
动态库: DLL文件
静态库: LIB文件
1.4.3 执行
DOS程序:只能运行在DOS窗口
窗口程序:独立窗口
动态库和静态库:不能独立运行
二 Win32开发环境
1 最常用的开发环境VC系统
VC1.5 -> VC6.0 -> (VC2005)VC2008 SP1 -> VC2010
2 VC的编译工具
2.1 编译器
CL.EXE - 将源代码编译成OBJ文件
2.2 链接器
LINK.EXE - 链接目标代码,生成执行文件或DLL
2.3 资源编译器
RC.EXE - 将资源脚本编译成RES文件,会链接到
程序当中。
3 Windows库和头文件
3.1 Windows的库
kernel32.lib - 包括进程、线程、内存管理等API
user32.lib - 包括窗口、交互消息等API
gdi32.lib - 包括各种绘图操作的API
3.2 Windows的头文件
windows.h - 包含了各种常用的windows头文件
windef.h - 定义各种常用的数据类型
winnt.h - 定义了Unicode编码支持
winbase.h - 定义 kernel32 的API
wingdi.h - 定义 gdi32 的API
winuser.h - 定义 user32 的API
4 Hello World 编写
4.1 WinMain
int WINAPI WinMain(
HINSTANCE hInstance,//当前程序的实例句柄
HINSTANCE hPrevInstance, //前一个程序的实例句柄
LPSTR lpCmdLine, //命令行参数
int nCmdShow //窗口显示命令
);
4.2 MessageBox
5 编译环境的准备
VCVARS32.BAT - 在DOS窗口中执行,配置当前
VC的开发环境
6 CL编译器
CL -help 查看CL的相关参数
- /c 只编译不链接
- /I 指定头文件路径
- /Tc 指定编译的C文件
/Tp 指定编译的C++文件
大小写敏感
7 LINK链接器
LINK /? 查看LINK的相关参数
- /OUT: 链接生成的文件名称
- /LIBPATH: 库文件的路径
- /SUBSYTEM: 链接程序类型
不区分大小写
8 执行
三 编写第一个窗口程序
1 入口函数
2 注册窗口
ATOM RegisterClass(
CONST WNDCLASS *lpWndClass //注册的窗口类结构的地址
);
typedef struct _WNDCLASS {
UINT style; //窗口类的风格
WNDPROC lpfnWndProc; //窗口处理函数的地址
int cbClsExtra; //窗口类附加数据
int cbWndExtra; //窗口附加数据
HANDLE hInstance; //当前应用程序的实例句柄
HICON hIcon; //图标句柄
HCURSOR hCursor; //光标的句柄
HBRUSH hbrBackground; //背景画刷
LPCTSTR lpszMenuName; //菜单资源
LPCTSTR lpszClassName; //窗口类的名称
} WNDCLASS;
3 定义窗口函数
LRESULT CALLBACK WindowProc(
HWND hwnd, //窗口句柄
UINT uMsg, //消息ID
WPARAM wParam, //消息附加参数
LPARAM lParam //消息附加参数
);
4 创建窗口
HWND CreateWindow(
LPCTSTR lpClassName, //窗口类名称
LPCTSTR lpWindowName, //窗口名
DWORD dwStyle, //窗口风格
int x, //窗口的左上角X坐标
int y, //窗口的左上角Y坐标
int nWidth, //窗口宽
int nHeight, //窗口的高
HWND hWndParent, //父窗口句柄
HMENU hMenu, //菜单句柄
HANDLE hInstance, //应用程序实例句柄
LPVOID lpParam //创建附加参数
);
创建成功返回窗口句柄
5 显示窗口
ShowWindow - 显示或隐藏窗口
UpdateWindow - 更新窗口画面
6 消息循环
GetMessage - 获取消息
DispatchMessage - 派发消息
四 资源的使用
1 定义图标
ICON
2 定义资源脚本
定义资源的ID和路径、数据等信息
文件类型:.rc
3 RC编译资源
使用RC编译成 .res 文件
4 链接到程序
使用Link 将res链接到程序当中
动态链接库文件 dll
#include "stdafx.h"
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
return TRUE;
}
Day 02=========================day02=============================================================================================================
一 NMAKE 和 Makefile 文件
1 NMAKE - 命令解释器,根据Makefile文件编译
链接项目
Makefile - 定义了编译和链接项目的脚本
2 Makefile 基本语法
描述块
依赖行 A : B
命令行 CL XXX.C /c
定义变量 CC = CL.exe
3 Makefile 执行过程
3.1 构建依赖树
1) 在Makefile文件中查找依赖行,如果未指定
依赖行,会在文件中查找第一个依赖行
例如 例子中ALL
2) 根据依赖行,构造整个Makifile的依赖树
例如: A : B
B : C
C : D
依赖树:
A
|-B
|-C
|-D
3.2 执行命令行
根据依赖树,从最底层依赖行开始执行命令,
依次往上层执行。
例如: D -> C -> B -> A
3.3 时间戳(time stampe)
比较文件的最后一次修改时间,是不是在依赖
项的修改时间之后。
二 字符编码
1 字符编码历史
1.1 ASCII
使用7位表示1个字符,用0-127表示128个字符
1.2 扩展ASCII
使用8位表示1个字符,用0-255表示256个字符。
代码页(Code page):通过代码页可以切换
数字所代表的字符。
1.3 多字节字符集 DBCS
使用8位或者16位表示一个字符。
例如:字符串 A程B序
65 A0 | 01 66 A0 02
由于8位和16位混合,所以在字符串解析时,
需要从第一个字节解析。
1.4 UNICODE字符集
使用16位表示1个字符,可以表示65536个字符。
例如:A - 0x0040
推广不利
占用更多的资源
2 C语言和编码
2.1 单字节字符
char/char *
2.2 宽字符
wchar/wchar *
2.3 宽字符函数
wprintf/wcslen 等支持widechar的字符处理函数
2.4 TCHAR
#ifdef _UNICODE
typedef wchar_t TCHAR
__T(x) L##x
#else
typedef char TCHAR
__T(x) x
#endif
2.5 UNICODE输出
printf对UNICODE的输出支持不好,因此在
Windows控制台下,需要输出UNICODE字符串时,
使用 WriteConsole 函数
BOOL WriteConsole(
HANDLE hConsoleOutput,//控制台输出句柄
CONST VOID *lpBuffer, //输出字符或字符串地址
DWORD nNumberOfCharsToWrite,
//字符串的长度
LPDWORD lpNumberOfCharsWritten,
//已输出的字符数量
LPVOID lpReserved // reserved
);
3 字符和Windows API
3.1 Windows API提供了多字节字符和宽字节
字符的支持,例如:
MessageBox包括 MessageBoxA 和
MessageBoxW
#ifdef UNICODE
#define MessageBox MessageBoxW
#else
#define MessageBox MessageBoxA
#endif // !UNICODE
可以使用UNICODE宏切换API使用版本。
3.2 字符集转换
MultiByteToWideChar - 多字节字符串转换
到宽字节字符串
int MultiByteToWideChar(
UINT CodePage, //code page,默认CP_ACP
DWORD dwFlags, //字符类型选项
LPCSTR lpMultiByteStr, // 多字节字符串的地址
int cchMultiByte, // 多字节字符串的长度
LPWSTR lpWideCharStr,
// 宽字节的BUFF的地址
int cchWideChar
// 宽字节的BUFF的长度
);
WideCharToMultiByte - 宽字节字符串转换
都多字节字符串
int WideCharToMultiByte(
UINT CodePage, // code page
DWORD dwFlags, // 转换时优化和效率
LPCWSTR lpWideCharStr, //Wide char字符串的地址
int cchWideChar, //Wide char字符串的地址长度
LPSTR lpMultiByteStr, //多字节字符串的BUFF
int cchMultiByte, //多字节字符串的BUFF长度
LPCSTR lpDefaultChar, //缺省字符串的地址
LPBOOL lpUsedDefaultChar //是否使用的标示
);
三 Windows窗口的注册和创建
1 窗口程序建立过程
1.1 入口函数
1.2 定义窗口处理函数
1.3 注册窗口类
RegisterClass
1.4 创建窗口
CreateWindow
1.5 显示窗口
1.6 消息处理
1.7 退出处理
2 注册窗口类
2.1 窗口类的分类
2.1.1 系统全局窗口类
系统已经定义好的窗口类,可以在程序中
直接使用,例如 按钮、编辑框。不需要
使用RegisterClass注册。
2.1.2 应用程序全局窗口类
只能在本应用程序中使用的窗口类,需要
使用RegisterClass注册。
2.1.3 应用程序局部窗口类
只能在本应用程序中本模块(EXE/DLL)使用
的窗口类,需要使用RegisterClass注册.
2.2 窗口类的使用
2.2.1 系统全局窗口类
直接使用窗口类的名称,调用CreateWindow
创建窗口。
Helloworld.rc的内容
100 ICON setup.ico
Building.bat的内容
rc Hellownd.rc
cl Hellownd.c /c
link HelloWnd.obj HelloWnd.res user32.lib
Makefile.mak的内容
CL=cl.exe
RC=rc.exe
LINK=link.exe
CL_FLAG=/c
LINK_LIB=user32.lib
ALL:DELETE
$(CL) $(CL_FLAG) hellownd.c
$(RC) hellownd.rc
$(LINK) $(LINK_LIB) hellownd.obj hellownd.res
===================================day03====================================================================================================
一 Windows窗口的注册和创建
1 窗口程序建立过程
1.1 入口函数
1.2 定义窗口处理函数
1.3 注册窗口类
RegisterClass
1.4 创建窗口
CreateWindow
1.5 显示窗口
1.6 消息处理
1.7 退出处理
2 注册窗口类
2.1 窗口类的分类
2.1.1 系统全局窗口类
系统已经定义好的窗口类,可以在程序中
直接使用,例如 按钮、编辑框。不需要
使用RegisterClass注册。
2.1.2 应用程序全局窗口类
只能在本应用程序中使用的窗口类,需要
使用RegisterClass注册。
2.1.3 应用程序局部窗口类
只能在本应用程序中本模块(EXE/DLL)使用
的窗口类,需要使用RegisterClass注册.
2.2 窗口类的使用
2.2.1 系统全局窗口类
直接使用窗口类的名称,调用CreateWindow
创建窗口。
2.2.2 应用程序全局窗口类
WNDCLASS wc;
wc.style = CS_GLOBALCLASS|.....;
应用程序全局窗口类的注册,WNDCLASS中的
需要增加style参数需要增加CS_GLOBALCLASS。
2.2.3 应用程序局部窗口类
不使用CS_GLOBALCLASS风格的窗口类。
注册窗口类使用API
RegisterClass/RegisterClassEx
typedef struct _WNDCLASSEX {
UINT cbSize; //WNDCLASSEX结构的大小
UINT style;
WNDPROC lpfnWndProc;
int cbClsExtra;
int cbWndExtra;
HANDLE hInstance;
HICON hIcon; //图标的句柄
HCURSOR hCursor;
HBRUSH hbrBackground;
LPCTSTR lpszMenuName;
LPCTSTR lpszClassName;
HICON hIconSm; //小图标的句柄
} WNDCLASSEX;
窗口类的风格:
CS_BYTEALIGNCLIENT 窗口客户区的X坐标以8的倍数对齐
CS_BYTEALIGNWINDOW 窗口的X坐标以8的倍数对齐
CS_CLASSDC 创建出的窗口都使用一个DC
CS_OWNDC 创建出的窗口都使用各自的DC
CS_PARENTDC 创建出的窗口使用其父窗口的DC
CS_HREDRAW 表示窗口水平移动或者大小变化时重绘窗口
CS_VREDRAW 表示窗口垂直移动或者大小变化时重绘窗口
CS_SAVEBITS 将窗口的画面以位图的方式保存
CS_DBLCLKS 允许窗口接收鼠标双击消息
CS_NOCLOSE 关闭窗口菜单中的“关闭”命令
2.2.4 窗口类附加数据 cbClsExtra
为窗口类提供一个内存空间,可以存储
或者获取数据。长度一般是4字节的倍数。
例如:100个字节( LONG[25] )
需要使用API
DWORD SetClassLong(
HWND hWnd, //窗口句柄
int nIndex, //字节为单位的索引
LONG dwNewLong //值
);
DWORD GetClassLong(
HWND hWnd, //窗口句柄
int nIndex //字节为单位的索引
); 返回获取到值
窗口类的数据对于所有它的窗口时公共的。
2.2.5 窗口附加数据 cbWndExtra
为窗口提供一个内存空间,可以存储
或者获取数据。长度一般是4字节的倍数。
需要使用API
LONG SetWindowLong(
HWND hWnd, //窗口句柄
int nIndex, //字节为单位的索引
LONG dwNewLong //值
);
LONG GetWindowLong(
HWND hWnd, //窗口句柄
int nIndex //字节为单位的索引
); 返回获取到值
窗口附加数据时属于窗口各自拥有。
2.3 相关的API函数
RegisterClass/Ex
UnregisterClass
GetClassLong
SetClassLong
SetWindowLong //
SetWindowLong //
2.4 创建窗口时窗口类的查找方式
2.4.1 首先在应用程序局部窗口类表中查找
对应的窗口类信息。如果未找到,执行2.4.2。
如果找到,比较HINSTANCE,如果句柄相同,
创建窗口,否则句柄不等,继续执行2.4.2。
2.4.2 在应用程序全局窗口类中查找,
如果未找到,执行2.4.3。如果找到,不
需要比较HINSTANCE,创建窗口返回。
2.4.3 在系统全局窗口类中查找,如果找到,
创建窗口返回,否则创建窗口失败。
3 窗口的创建
3.1 窗口的创建
CretaeWindow/CretaeWindowEx
HWND CreateWindowEx(
DWORD dwExStyle, //窗口扩展风格
LPCTSTR lpClassName, // pointer to registered class name
LPCTSTR lpWindowName, // pointer to window name
DWORD dwStyle, // window style
int x, // horizontal position of window
int y, // vertical position of window
int nWidth, // window width
int nHeight, // window height
HWND hWndParent, // handle to parent or owner window
HMENU hMenu, // handle to menu, or child-window identifier
HINSTANCE hInstance, // handle to application instance
LPVOID lpParam // pointer to window-creation data
);
每个窗口都具有窗口处理函数。当窗口产生
任何消息时,系统会调用窗口处理函数,我们
在这个函数中处理相应的情况。
3.2 父窗口和子窗口
创建时,在CreateWindow可以指定其父窗口,
当父窗口关闭时,子窗口随之关闭。
3.3 MDI窗口的创建
3.3.1 主窗口
注册并创建主窗口。CreateWindowEx
主窗口的窗口处理函数默认调用DefFrameProc;
LRESULT DefFrameProc(
HWND hWnd, // handle to MDI frame window
HWND hWndMDIClient, // handle to MDI client window
UINT uMsg, // message
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
);
3.3.2 MDICLIENT窗口
使用“MDICLENT”窗口类创建窗口,其父窗口
为主窗口。
3.3.3 子窗口
注册并创建子窗口,其父窗口为MDICLIENT窗口。
子窗口的窗口处理函数默认调用 DefMDIChildProc
LRESULT DefMDIChildProc(
HWND hWnd, // handle to MDI child window
UINT uMsg, // message
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
);
//设置窗口类附加数据
void SetClsExtra( HWND hWnd )
{
SetClassLong( hWnd, 0, 100 );
}
//获取窗口类附加数据
void GetClsExtra( HWND hWnd )
{
DWORD nValue = GetClassLong( hWnd, 0 );
CHAR szText[256] = { 0 };
sprintf( szText, "%d", nValue );
MessageBox( NULL, szText, "WinReg", MB_OK );
}
//设置窗口附加数据
void SetWndExtra( HWND hWnd )
{
SetWindowLong( hWnd, 1, 200 );
}
//获取窗口附加数据
void GetWndExtra( HWND hWnd )
{
LONG nValue = GetWindowLong( hWnd, 1 );
CHAR szText[256] = { 0 };
sprintf( szText, "WndExtra: %d", nValue );
MessageBox( NULL, szText, "WinReg", MB_OK );
}
创建父子窗口
// WinCreate.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
HINSTANCE g_hInst = NULL;
LRESULT CALLBACK ParentProc( HWND hWnd,
UINT nMsg,
WPARAM wParam,
LPARAM lParam )
{
return DefWindowProc( hWnd, nMsg, wParam, lParam );
}
LRESULT CALLBACK ChildProc( HWND hWnd,
UINT nMsg,
WPARAM wParam,
LPARAM lParam )
{
return DefWindowProc( hWnd, nMsg, wParam, lParam );
}
HWND CreateParent( LPSTR pszClassName )
{
HWND hWnd = CreateWindowEx( 0, pszClassName,
"ParentWnd",WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_THICKFRAME|WS_MAXIMIZEBOX, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, g_hInst, NULL );
return hWnd;
}
HWND CreateChild( LPSTR pszClassName, HWND hParentWnd )
{
HWND hWnd = CreateWindowEx( WS_EX_TOOLWINDOW, pszClassName,
"ChildWnd", WS_OVERLAPPEDWINDOW|WS_CHILD|WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT, hParentWnd,
NULL, g_hInst, NULL );
return hWnd;
}
void DisplayWnd( HWND hWnd )
{
ShowWindow( hWnd, SW_SHOW );
UpdateWindow( hWnd );
}
void Message( )
{
MSG msg = { 0 };
while( GetMessage( &msg, NULL, 0, 0 ) )
{
DispatchMessage( &msg );
}
}
BOOL RegisterWnd( LPSTR pszClassName,
WNDPROC proc,
int nBackground )
{
WNDCLASSEX wce = { 0 };
wce.cbSize = sizeof( WNDCLASSEX );
wce.cbClsExtra = 0;
wce.cbWndExtra = 0;
wce.lpfnWndProc = proc;
wce.hInstance = g_hInst;
wce.hIcon = NULL;
wce.hCursor = NULL;
wce.hbrBackground = (HBRUSH)nBackground;
wce.lpszMenuName = NULL;
wce.lpszClassName = pszClassName;
wce.style = CS_HREDRAW|CS_VREDRAW;
wce.hIconSm = NULL;
ATOM nAtom = RegisterClassEx( &wce );
if( 0 == nAtom )
{
return FALSE;
}
return TRUE;
}
int APIENTRY WinMain( HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
g_hInst = hInstance;
//注册父窗口类
RegisterWnd( "PARENTWND", ParentProc,
COLOR_BTNTEXT );
//注册子窗口类
RegisterWnd( "CHILDWND", ChildProc,
COLOR_BTNTEXT+1 );
//创建父窗口
HWND hParentWnd = CreateParent( "PARENTWND" );
//创建子窗口
HWND hChildWnd1 = CreateChild( "CHILDWND", hParentWnd );
HWND hChildWnd2 = CreateChild( "CHILDWND", hParentWnd );
//移动子窗口
MoveWindow( hChildWnd1, 0, 0, 100, 100, TRUE );
MoveWindow( hChildWnd2, 200, 200, 100, 100, TRUE );
//显示窗口
DisplayWnd( hParentWnd );
Message( );
return 0;
}
#include "stdafx.h"
#include "resource.h"
HINSTANCE g_hInst = NULL;
//MDICLIENT窗口句柄
HWND g_hMDIClientWnd = NULL;
//主窗口处理函数
LRESULT CALLBACK MainProc( HWND hWnd,
UINT nMsg,
WPARAM wParam,
LPARAM lParam )
{
switch( nMsg )
{
case WM_DESTROY:
PostQuitMessage( 0 );
break;
}
//默认调用DefFrameProc
return DefFrameProc( hWnd,
g_hMDIClientWnd, nMsg, wParam, lParam );
}
//子窗口处理函数
LRESULT CALLBACK ChildProc( HWND hWnd,
UINT nMsg,
WPARAM wParam,
LPARAM lParam )
{ //默认调用DefMDIChildProc
return DefMDIChildProc( hWnd, nMsg,
wParam, lParam );
}
BOOL RegisterWnd( LPSTR pszClassName,
WNDPROC proc,
int nBackground )
{
WNDCLASSEX wce ={ 0 };
wce.cbSize = sizeof( wce );
wce.style = CS_HREDRAW|CS_VREDRAW;
wce.cbWndExtra = 0;
wce.cbClsExtra = 0;
wce.lpfnWndProc = proc;
wce.hIcon = NULL;
wce.hCursor = NULL;
wce.hIconSm = NULL;
wce.hInstance = g_hInst;
wce.hbrBackground = (HBRUSH)nBackground;
wce.lpszMenuName = MAKEINTRESOURCE( IDR_MENU1 );
wce.lpszClassName = pszClassName;
ATOM nAtom = RegisterClassEx( &wce );
if( 0 == nAtom )
{
return FALSE;
}
return TRUE;
}
//显示窗口
void DisplayWnd( HWND hWnd )
{
ShowWindow( hWnd, SW_SHOW );
UpdateWindow( hWnd );
}
//消息处理
void Message( )
{
MSG msg = { 0 };
while( GetMessage( &msg, NULL, 0, 0 ) )
{
DispatchMessage( &msg );
}
}
//创建主窗口
HWND CreateMain( LPSTR pszClassName )
{
HWND hWnd = CreateWindowEx( 0, pszClassName,
"MDIMain", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, g_hInst, NULL );
return hWnd;
}
//创建MDI Client窗口
HWND CreateMDIClient( HWND hMain )
{
CLIENTCREATESTRUCT cs = { 0 };
cs.hWindowMenu = NULL;
cs.idFirstChild = 1000;
HWND hWnd = CreateWindowEx( 0, "MDICLIENT",
"MDIClient", WS_CHILD|WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
hMain, NULL, g_hInst, &cs );
return hWnd;
}
//创建MDI子窗口
HWND CreateChild( LPSTR pszClassName,
LPSTR pszWndName,
HWND hParent )
{
HWND hWnd = CreateWindowEx( WS_EX_MDICHILD,
pszClassName,
pszWndName,
WS_CHILD|WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
hParent, NULL, g_hInst, NULL );
ShowWindow( hWnd, SW_SHOW );
return hWnd;
}
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
g_hInst = hInstance;
//注册主窗口类
RegisterWnd( "MAINWND", MainProc, COLOR_WINDOW );
//注册子窗口类
RegisterWnd( "CHILDWND", ChildProc, COLOR_WINDOW );
//创建主窗口
HWND hMainWnd = CreateMain( "MAINWND" );
//创建MDICLIENT窗口
g_hMDIClientWnd = CreateMDIClient( hMainWnd );
//显示主窗口
DisplayWnd( hMainWnd );
//创建子窗口
CreateChild( "CHILDWND", "Child-1", g_hMDIClientWnd );
CreateChild( "CHILDWND", "Child-2", g_hMDIClientWnd );
CreateChild( "CHILDWND", "Child-3", g_hMDIClientWnd );
//消息处理
Message( );
return 0;
}
=====================================day04==================================================================================================
一 Windows消息机制
1 消息机制概述
过程驱动 - 程序的执行过程是预先定义好的。
事件驱动 - 程序的执行过程是随机的,是由
使用者来决定。
Windows消息机制是采用事件驱动的方式。
2 消息的使用
2.1 窗口注册
2.2 窗口创建
2.3 消息的处理
GetMessage - 获取消息
BOOL GetMessage(
LPMSG lpMsg, //存放获取到消息的MSG结构地址
HWND hWnd, //指定窗口的消息
UINT wMsgFilterMin, //接收最小消息ID
UINT wMsgFilterMax // 接收最大消息ID
);
DispatchMessage - 派发消息,根据窗口句柄
找到对应的窗口处理函数并调用,将消息
参数传给窗口处理函数。
LONG DispatchMessage(
CONST MSG *lpmsg // pointer to structure with message
);
TranslateMessage - 将按键消息转换为字符消息
BOOL TranslateMessage (
CONST MSG *lpMsg // address of structure with message
);
2.4 常用的窗口消息
2.4.1 WM_CREATE - 窗口创建成功后,收到的
第一条消息。
WPARAM - 未使用
LPARAM - CREATESTRUCT结构指针
实现初始化操作。
2.4.2 WM_DESTROY - 窗口销毁时的消息
2.4.3 WM_SIZE - 窗口大小发生变化后得到的消息。
wParam - 变化时的标识
nWidth = LOWORD(lParam); 客户区的宽度
nHeight = HIWORD(lParam); 客户区的宽度
可以实现在窗口大小变化后,调整窗口内
各部分的位置的操作。
2.4.4 WM_SYSCOMMAND - 当点击窗口上最大化、
关闭等按钮时,会收相应消息。
uCmdType = wParam; //触发的命令的类型
xPos = LOWORD(lParam); // 鼠标的位置X
yPos = HIWORD(lParam); // 鼠标的位置Y
2.4.5 WM_PAINT - 绘制屏幕消息,实现绘图功能。
2.4.6 鼠标消息
2.4.7 键盘消息
2.4.8 定时器消息
2.5 消息的获取和发送
2.5.1 消息的获取
GetMessage/PeekMessage
GetMessage - 获得消息,是一个阻塞函数。
PeekMessage - 检查消息,非阻塞函数。
2.5.2 消息的发送
SendMessage/PostMessage
SendMessage - 发送消息,需要等候消息处理
返回。
PostMessage - 投递消息,不需等候立刻返回。
3 消息和消息的结构
3.1 消息
Windows窗口程序都是通过消息进行传递,处理
相应的操作。
3.2 消息的结构
窗口句柄、消息ID、附加参数WPARAM/LPARAM
3.3 消息分类
3.3.1 系统定义的窗口消息。例如WM_CREATE
消息ID的范围是 0x0000 - 0x03FF
3.3.2 用户自定义消息, 消息ID的范围是
0x0400 - 0x7FFF。消息定义采用
WM_USER + N
3.3.3 应用程序消息 WM_APP - 0xC000
3.3.4 字符串注册消息 大于0xC000
4 消息队列
Windows用先进先出的队列维护消息。
4.1 系统消息队列
由操作系统维护的消息队列。
4.2 应用程序消息队列(线程消息队列)
各个线程都具有自己的消息队列。
5 消息和消息队列
根据消息和消息队列之间的使用关系,将消息
分成两大类。
5.1 队列消息
进入到消息队列中的消息。例如:鼠标、
键盘、WM_PAINT、WM_TIMER、WM_QUIT。
使用 PostMessage 发送消息
5.2 非队列消息
不进入消息队列,直接发送给指定的窗口。
例如:WM_CREATE,WM_SIZE,WM_DESTROY
使用 SendMessage 发送消息。
6 消息的获取
GetMessage和PeekMessage消息的获取
6.1 从线程消息队列中获取消息。如果队列中有
消息,获取消息并返回。如果未获取,执行6.2
6.2 从系统消息队列中检索消息,查找到属于
自己应用程序的消息,如果找到,获取消息并
返回。如果未找到,执行6.3.
6.3 检查窗口需要重绘的区域,如果检查到,
产生WM_PAINT消息并返回,如果未找到,执行6.4
6.4 检查定时器,如果有到时的定时器,
产生WM_TIMER消息并返回,如果未找到,执行6.5
6.5 内存整理,例如绘图对象。
6.6 GetMessage - 阻塞并等候下一条消息的来临。
PeekMessage - 让出控制权,让程序继续执行。
7 消息的发送
PostMessage - 将消息放入线程消息队列,
立刻返回。消息不能确定是否被正确响应。
SendMessage - 直接将消息发送到指定窗口的
窗口处理函数,并获取消息的执行结果。
二 WM_PAINT 消息
1 绘制窗口消息
当窗户中有无效绘图的区域,就会产生WM_PAINT消息。
可以使用API InvalidateRect产生无效区域。
2 WM_PAINT消息的使用
2.1 在WM_PAINT消息开始添加 BeginPaint
2.2 绘图操作
2.3 在WM_PAINT消息结束添加 EndPaint
#include "stdafx.h"
#include "stdio.h"
HINSTANCE g_hInst = NULL;
HANDLE g_hStdOut = NULL;
LRESULT CALLBACK WndProc( HWND hWnd,
UINT nMsg,
WPARAM wParam,
LPARAM lParam )
{
CHAR szMsg[256] = { 0 };
sprintf( szMsg, "MSG ID: %04X\n", nMsg );
WriteConsole( g_hStdOut, szMsg, strlen( szMsg ), NULL, NULL );
switch( nMsg )
{
case WM_CREATE:
WriteConsole( g_hStdOut, "WM_CREATE",
strlen( "WM_CREATE" ), NULL, NULL );
break;
case WM_DESTROY:
PostQuitMessage( 0 );
break;
}
return DefWindowProc( hWnd, nMsg,
wParam, lParam );
}
BOOL RegisterWnd( LPSTR pszClassName )
{
WNDCLASSEX wce = { 0 };
wce.cbSize = sizeof( wce );
wce.cbClsExtra = 0;
wce.cbWndExtra = 0;
wce.hInstance = g_hInst;
wce.style = CS_HREDRAW|CS_VREDRAW;
wce.hIcon = NULL;
wce.hCursor = NULL;
wce.hbrBackground = (HBRUSH)(COLOR_WINDOW);
wce.lpfnWndProc = WndProc;
wce.lpszMenuName = NULL;
wce.lpszClassName = pszClassName;
wce.hIconSm = NULL;
ATOM nAtom = RegisterClassEx( &wce );
if( 0 == nAtom )
{
return FALSE;
}
return TRUE;
}
HWND CreateWnd( LPSTR pszClassName )
{
HWND hWnd = CreateWindowEx( 0, pszClassName,
"WinMsg", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, g_hInst, NULL );
return hWnd;
}
void DisplayWnd( HWND hWnd )
{
ShowWindow( hWnd, SW_SHOW );
UpdateWindow( hWnd );
}
void Message( )
{
MSG msg = { 0 };
//获取消息
while( GetMessage( &msg, NULL, 0, 0 ) )
{ //将按键消息转换成字符消息
TranslateMessage( &msg );
//派发消息
DispatchMessage( &msg );
}
}
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
g_hInst = hInstance;
//打开一个控制台窗口
AllocConsole( );
g_hStdOut = GetStdHandle( STD_OUTPUT_HANDLE );
RegisterWnd( "WINMSG" );
HWND hWnd = CreateWnd( "WINMSG" );
DisplayWnd( hWnd );
Message( );
return 0;
}
********************************创建一个按钮****************************
void OnCreate( HWND hWnd, WPARAM wParam, LPARAM lParam )
{
LPCREATESTRUCT pCreateStruct =
( LPCREATESTRUCT )lParam;
WriteConsole( g_hStdOut, pCreateStruct->lpszClass,
strlen( pCreateStruct->lpszClass ), NULL, NULL );
CreateWindowEx( 0, "BUTTON", "Test",
WS_CHILD|WS_VISIBLE, 100, 100, 200, 40,
hWnd, NULL, g_hInst, NULL );
}
***************************************************************************
BOOL OnSysCommand( HWND hWnd, WPARAM wParam, LPARAM lParam )
{
switch( wParam )
{
case SC_CLOSE:
if( IDCANCEL == MessageBox( NULL, "是否退出应用程序?",
"WinMsg", MB_OKCANCEL ) )
{
return FALSE;
}
break;
}
return TRUE;
}
*******************************************************************************void OnSize( HWND hWnd, WPARAM wParam, LPARAM lParam )
{
int nWidth = LOWORD( lParam );
int nHeight = HIWORD( lParam );
CHAR szText[256] = { 0 };
sprintf( szText, "WM_SIZE: W %d H %d\n",
nWidth, nHeight );
WriteConsole( g_hStdOut, szText,
strlen( szText ), NULL, NULL );
}
*******************************************************************************
发送用户自定义消息
#define WM_FIRSTMSG ( WM_USER + 1 )
#define WM_SECONDMSG ( WM_USER + 2 )
SendMessage( hWnd, WM_FIRSTMSG, 0, 0 );
*******************************************************************************
void OnPaint( HWND hWnd, WPARAM wParam, LPARAM lParam )
{ //初始化WM_PAINT
PAINTSTRUCT ps = { 0 };
HDC hDC = BeginPaint( hWnd, &ps );
//绘图操作
CHAR szText[256] = "hello WM_PAINT";
TextOut( hDC, 100, 100, szText,
strlen( szText ) );
//结束WM_PAINT
EndPaint( hWnd, &ps );
}
*******************************************************************************
============================day05==========================================================================================================
一 菜单和命令
1 菜单
菜单 - 使用一个 HMENU 句柄表示。
菜单项 - 每一个菜单项都具有一个ID号,可以
根据这个ID,执行不同的命令。
2 菜单的相关
CreateMenu - 创建菜单
DestroyMenu - 销毁菜单
AppendMenu - 追加菜单项
InsertMenu - 插入菜单项
DeleteMenu - 删除菜单项
...
3 菜单的使用
3.1 创建一个菜单
HMENU CreateMenu(VOID)
3.2 创建一个弹出式菜单 PopupMenu
HMENU CreatePopupMenu(VOID)
3.3 增加菜单项
AppendMenu/InsertMenu
BOOL AppendMenu(
HMENU hMenu, //菜单句柄
UINT uFlags, //菜单项的标志
UINT uIDNewItem, //菜单项的ID或菜单句柄
LPCTSTR lpNewItem //菜单项名称
);
3.4 显示菜单
BOOL SetMenu(
HWND hWnd, // handle to window
HMENU hMenu // handle to menu
);
3.5 菜单的命令处理
当点击菜单项时,窗口会收到WM_COMMAND消息。
wNotifyCode = HIWORD(wParam);
//通知代码,对于菜单项为0
wID = LOWORD(wParam);
//菜单项的ID
hwndCtl = (HWND) lParam;
//控件窗口句柄,对于菜单项为NULL
3.6 菜单项状态的修改
3.6.1 在弹出式菜单显示之前,会收到
WM_INITMENUPOPUP消息,消息里可以完成
菜单项状态修改
hmenuPopup = (HMENU) wParam;
//弹出菜单的句柄
uPos = (UINT) LOWORD(lParam);
//菜单位置
fSystemMenu = (BOOL) HIWORD(lParam);
//标识是否是系统菜单
3.6.2 使用API函数
CheckMenuItem
EnableMenuItem
SetMenuItemInfo
4 系统菜单
4.1 系统菜单的获取
HMENU GetSystemMenu(
HWND hWnd, // handle to window to own window menu
BOOL bRevert // reset flag
);
4.2 系统菜单命令处理,是在WM_SYSCOMMAND中完成。
5 右键菜单 Context Menu
5.1 右键菜单
5.2 右键菜单的使用
5.2.1 创建弹出式菜单
HMENU CreatePopupMenu(VOID)
AeppendMenu
InsertMenu
5.2.2 显示菜单
BOOL TrackPopupMenu(
HMENU hMenu, //菜单句柄
UINT uFlags,//菜单的显示方式
int x, //菜单X坐标,以屏幕坐标系
int y, //菜单Y坐标,以屏幕坐标系 // vertical position, in screen coordinates
int nReserved,//保留,为0
HWND hWnd, //处理菜单命令的窗口句柄
CONST RECT *prcRect //忽略,设置为NULL
);
5.2.3 菜单的命令处理
WM_COMMAND
如果菜单显示时设置了TPM_RETURNCMD标识,
那么不会发送WM_COMMAND消息,而是将命令ID
通过函数返回值返回
5.3 处理右键菜单的消息
5.3.1 WM_RBUTTONUP
5.3.2 WM_CONTEXTMENU
WM_CONTEXTMENU消息是在WM_RBUTTONUP之后产生。
二 资源的使用
1 资源
图标、鼠标、菜单、加速键、字符串、
对话框资源、图片、自定义资源等。
2 图标
图标的常用大小 16X16 32X32 48X48
LoadIcon 加载图标
HICON LoadIcon(
HINSTANCE hInstance, //应用程序实例句柄
LPCTSTR lpIconName //ICON的ID名称
); 返回HICON句柄
3 光标
3.1 光标的使用
光标常用大小 16X16 32X32
热点 - 光标能够产生点击效果的点,1个像素
大小
LoadCursor 加载光标
3.2 WM_SETCURSOR
在消息内可以设置光标样式。
4 字符串
4.1 添加字符串资源
4.2 加载字符串资源
int LoadString(
HINSTANCE hInstance, //应用程序句柄
UINT uID, //字符串ID
LPTSTR lpBuffer, //存放字符串的BUFF
int nBufferMax //BUFF的大小
);
5 菜单
5.1 添加菜单资源
5.2 加载菜单资源
HMENU LoadMenu(
HINSTANCE hInstance, //应用程序句柄
LPCTSTR lpMenuName //菜单的ID
); 返回菜单的句柄
6 加速键
6.1 添加加速键的资源
6.2 加载加速键
HACCEL LoadAccelerators(
HINSTANCE hInstance, //应用程序句柄
LPCTSTR lpTableName //加速键表的ID
); 返回加载加速键表句柄
6.3 增加加速键的消息处理
int TranslateAccelerator(
HWND hWnd, //处理消息的窗口句柄
HACCEL hAccTable, //加速键句柄
LPMSG lpMsg //需要转换消息
);
6.4 处理过程
TranslateAccelerator 会根据MSG消息,查看
hAccTable,如果发现对应按键消息能够与表
中的命令ID对应,发送一条WM_COMMAND或者
WM_SYSCOMMAND消息到窗口。
创建菜单
void OnCreate( HWND hWnd )
{ //创建顶层菜单
HMENU hMainMenu = CreateMenu( );
//创建弹出式菜单
HMENU hSubMenu = CreatePopupMenu( );
HMENU hEditMenu = CreatePopupMenu( );
//增加菜单项
AppendMenu( hSubMenu, MF_STRING, 1000, "&Open" );
AppendMenu( hSubMenu, MF_SEPARATOR, 0, NULL );
AppendMenu( hSubMenu, MF_STRING, 1001, "E&xit" );
AppendMenu( hEditMenu, MF_STRING|MF_CHECKED, 1101, "&Copy" );
AppendMenu( hEditMenu, MF_STRING|MF_DISABLED|MF_GRAYED, 1102, "&Past" );
//将弹出式菜单加入到顶层菜单
AppendMenu( hMainMenu, MF_POPUP,
(UINT)hSubMenu, "&File" );
AppendMenu( hMainMenu, MF_POPUP,
(UINT)hEditMenu, "&Edit" );
//显示菜单
SetMenu( hWnd, hMainMenu );
}
*******************************************************************************
case WM_CONTEXTMENU:
OnContextMenu( hWnd, wParam, lParam );
########################
HMENU CreateMyMenu( )
{
HMENU hMenu = CreatePopupMenu( );
AppendMenu( hMenu, MF_STRING, 1001, "&Open" );
AppendMenu( hMenu, MF_STRING, 1002, "E&xit" );
return hMenu;
}
#########################
void OnContextMenu( HWND hWnd, WPARAM wParam, LPARAM lParam )
{
int nXPos = LOWORD( lParam );
int nYPos = HIWORD( lParam );
HMENU hMenu = CreateMyMenu( );
int nCmd = TrackPopupMenu( hMenu,
TPM_LEFTALIGN|TPM_RETURNCMD,
nXPos, nYPos, 0, hWnd, NULL );
CHAR szText[256] = { 0 };
sprintf( szText, "TPM_RETURNCMD: %d\n", nCmd );
WriteConsole( g_hStdOutput, szText,
strlen(szText), NULL, NULL );
}
##############
wce.hCursor =
LoadCursor( g_hInst, MAKEINTRESOURCE( IDC_CURSOR1) );
wce.hIcon =
LoadIcon( g_hInst, MAKEINTRESOURCE( IDI_MAIN ) );
##############
case WM_SETCURSOR:
OnSetCursor( hWnd, wParam, lParam );
void OnSetCursor( HWND hWnd, WPARAM wParam, LPARAM lParam )
{ //判断鼠标是否在客户区内
int nHittest = LOWORD(lParam);
if( HTCLIENT != nHittest ) //HTCLIENT被定义为一个宏
{
DefWindowProc( hWnd, WM_SETCURSOR,
wParam, lParam );
return;
}
//获取当前光标的位置(屏幕坐标)
POINT point = { 0 };
GetCursorPos( &point );
//转换成客户区坐标
ScreenToClient( hWnd, &point );
//获取客户区的大小
RECT rcClient = { 0 };
GetClientRect( hWnd, &rcClient );
//判定鼠标在客户区的区域
if( point.x < rcClient.right/2 )
{
HCURSOR hCursor = LoadCursor( g_hInst,
MAKEINTRESOURCE( IDC_MAIN ) );
SetCursor( hCursor );
}
else
{
HCURSOR hCursor = LoadCursor( g_hInst,
MAKEINTRESOURCE( IDC_MAIN1 ) );
SetCursor( hCursor );
}
}
#########################
==================================day07====================================================================================================
一 Windows绘图
1 绘图设备
例如显示器、打印机等等,通过DC设备描述表
(Device Context),Windows程序中使用HDC
表示DC的句柄。
2 颜色
显示器颜色是通过Red、Green、Blue,每个
用8位表示,用24位表示一个颜色。可以
表示的颜色数量为 2的24次方。
常用颜色数量
16位色 - 颜色数量为2^16,
32位色 - 颜色数量为2^24, 高8位表示灰度
或者透明度
Window程序中使用 COLORREF 表示颜色数据
COLORREF nColor = RGB( 200, 200, 200 );
获取一个颜色的RGB值
GetRValue、GetGValue、GetBValue
3 点的绘制
COLORREF SetPixel(
HDC hdc, //DC句柄
int X, //DC的X坐标
int Y, //DC的Y坐标
COLORREF crColor //绘制的颜色
);
GetPixel 返回指定点的颜色
4 线的绘制
当前点 - 绘图的起始点。
4.1 直线
MoveToEx - 移动当前点到指定的位置
LineTo - 从当前点到指定位置绘制直线,
会改变当前点的位置到指定位置。
4.2 弧线
SetArcDirection - 设置切弧的方向
Arc - 绘制弧,不影响当前点
ArcTo - 影响当前点
AngelArc - 用角度绘制弧
4.3 折线
Polyline - 绘制折线
PolylineTo - 绘制折线并连接当前点
PolyPolyline - 绘制多组折线
4.4 Biezer曲线
PolyBezier - 绘制Biezer曲线
PolyBezierTo - 绘制Biezer曲线并连接当前点
5 封闭图形
5.1 矩形
Rectangle
RoundRect
5.2 椭圆
Ellipse
5.3 多边形
Polygon
5.4 扇形
Pie
5.5 弓形
Chord
二 绘图对象
1 绘图对象GDI Object
画笔、画刷、位图、字体
2 画笔的使用
2.1 画笔的作用
线的颜色、线的粗细、线的样式
2.2 画笔相关
2.2.1 HPEN 表示画笔的句柄
2.2.2 CreatePen( Indirect )
2.3 画笔的使用
2.3.1 创建画笔
HPEN CreatePen(
int fnPenStyle, //画笔样式
int nWidth, //画笔宽度
COLORREF crColor //画笔的颜色
);返回画笔句柄
2.3.2 将创建画笔放入DC中,同时取出旧画笔
HGDIOBJ SelectObject(
HDC hdc, //DC句柄
HGDIOBJ hgdiobj //绘图对象句柄
); 返回DC中原来的绘图对象句柄
2.3.3 绘制图形
2.3.4 恢复DC中的旧画笔,同时取出创建画笔
SelectObject
2.3.5 销毁画笔
BOOL DeleteObject(
HGDIOBJ hObject //删除绘图对象句柄
);
3 画刷的使用
3.1 画刷的作用
提供封闭区域的填充,填充样式、颜色。
3.2 画刷相关
3.2.1 HBRUSH 表示画刷的句柄
3.2.2 CreateSolidBrush 创建实心画刷
CreateHatchBrush 创建样式画刷
GetStockObject 获取NULL_BRUSH
3.3 画刷的使用
3.3.1 创建画刷
3.3.2 将创建画刷放入DC中,同时取出旧画刷
3.3.3 绘图操作
3.3.4 恢复DC中的旧画刷,同时取出创建画刷
3.3.5 删除画刷
4 位图
4.1 位图的基础
记录图像的每一点的颜色。
4.2 位图相关
4.2.1 HBITMAP 表示位图句柄
4.2.2 LoadBitmap 加载位图资源
4.3 位图的使用
4.3.1 加载位图
LoadBitmap
4.3.2 创建与当前DC相匹配的DC
HDC CreateCompatibleDC(
HDC hdc // handle to the device context
);
4.3.3 将位图放入创建的DC当中
SelectObject
4.3.4 绘制位图
BOOL BitBlt(
HDC hdcDest, //绘制位图的DC句柄
int nXDest, //绘制的X坐标
int nYDest, //绘制的Y坐标
int nWidth, //绘制的宽
int nHeight, //绘制的高
HDC hdcSrc, //要绘制的DC句柄
int nXSrc, //要绘制的DC X起点
int nYSrc, //要绘制的DC Y起点
DWORD dwRop //绘制方式
);
BOOL StretchBlt(
HDC hdcDest, // handle to destination device context
int nXOriginDest, // x-coordinate of upper-left corner of dest. rectangle
int nYOriginDest, // y-coordinate of upper-left corner of dest. rectangle
int nWidthDest, // width of destination rectangle
int nHeightDest, // height of destination rectangle
HDC hdcSrc, // handle to source device context
int nXOriginSrc, // x-coordinate of upper-left corner of source rectangle
int nYOriginSrc, // y-coordinate of upper-left corner of source rectangle
int nWidthSrc, // 原宽
int nHeightSrc, // 原高
DWORD dwRop // raster operation code
);
4.3.5 取出位图
SelectObject
4.3.6 销毁创建的DC和位图
DeleteDC
DeleteObject
##############################3
SetPixel( hDC, nX, nY, RGB( 255, 0, 0 ) );
COLORREF nColor = GetPixel( hDC, 100, 100 );
BYTE nRed = GetRValue( nColor );
BYTE nGreen = GetGValue( nColor );
BYTE nBlue = GetBValue( nColor );
MoveToEx( hDC, 200, 0, NULL );
//绘制直线
LineTo( hDC, 200, 200 );
LineTo( hDC, 400, 200 );
SetArcDirection( hDC, AD_CLOCKWISE );
//绘制弧线
Arc( hDC, 300, 100, 400, 200,
400, 100, 300, 100 );
LineTo( hDC, 0, 0 )
绘制折线
POINT ptPoint[6] = {
{ 100, 100 },
{ 200, 100 },
{ 200, 200 },
{ 300, 200 },
{ 300, 300 },
{ 400, 300 } };
//Polyline( hDC, ptPoint, 6 );
DWORD dwPolyPoints[2] = { 2, 4 };
PolyPolyline( hDC, ptPoint,
dwPolyPoints, 2 );
绘制贝塞尔曲线
POINT ptPoint[4] = {
{ 100, 100 },
{ 150, 50 },
{ 250, 150 },
{ 300, 100 } };
PolyBezier( hDC, ptPoint, 4 );
椭圆
Ellipse( hDC, 200, 200, 400, 300 );
画笔的使用
PAINTSTRUCT ps = { 0 };
HDC hDC = BeginPaint( hWnd, &ps );
HPEN hPen = NULL;
switch( g_nPenID )
{
case ID_PEN0:
hPen = CreatePen( PS_NULL, 1,
RGB( 0, 0, 0 ) );
//将画笔放入DC当中,并保存原来的画笔
HPEN hOldPen = (HPEN)SelectObject( hDC, hPen );
//取出创建的画笔,放入原来的画笔
SelectObject( hDC, hOldPen );
//销毁画笔
DeleteObject( hPen );
EndPaint( hWnd, &ps )
==================================day08====================================================================================================
一 坐标系和映射模式
1 坐标系的基础
1.1 设备坐标系
以设备单位(显示器-像素)为单位的坐标系。
1.1.1 屏幕坐标系 - 以屏幕的左上角为(0,0)点
向右为X正方向,向下为Y正方向
1.1.2 窗口坐标系 - 以窗口的左上角为(0,0)点
向右为X正方向,向下为Y正方向
1.1.3 客户区坐标系 - 以窗口客户区的左上角
为(0,0)点,向右为X正方向,向下为Y正方向
1.2 逻辑坐标系
以逻辑单位,例如毫米、英寸为单位的坐标系。
几乎所有的绘图函数,都使用的是逻辑坐标系
1.3 设备坐标系和逻辑坐标系
绘图时,使用逻辑坐标系,API内部进行转换,
将逻辑坐标转换到设备坐标,在设备上显示
对应图形。
2 映射模式
2.1 映射模式
逻辑坐标系和设备坐标系之间的对应关系
2.2 分类
MM_TEXT - 1个设备单位,X向右, Y向下
MM_LOMETRIC - 0.1毫米单位,X向右, Y向上
MM_HIMETRIC - 0.01毫米单位,X向右, Y向上
MM_LOENGLISH - 0.1in单位,X向右, Y向上
MM_HIENGLISH - 0.01in单位,X向右, Y向上
MM_TWIPS - 1/1440in单位,X向右, Y向上
MM_ISOTROPIC - 任意指定单位和正方向的
映射模式。X轴=Y轴
MM_ANISOTROPIC - 任意指定单位和正方向的
映射模式。X轴可以与Y轴不等。
2.3 映射的使用
SetMapMode
GetMapMode
2.4 MM_ISOTROPIC / MM_ANISOTROPIC 的使用
BOOL SetWindowExtEx(
HDC hdc, //DC句柄
int nXExtent, //X方向的长度,逻辑坐标
int nYExtent, //Y方向的长度,逻辑坐标
LPSIZE lpSize //原来的长度
);
BOOL SetViewportExtEx(
HDC hdc, //DC句柄
int nXExtent, //X方向的长度,设备坐标
int nYExtent, //Y方向的长度,设备坐标
LPSIZE lpSize //原来的长度
);
2.5 坐标原点
默认情况下,设备坐标系和逻辑坐标系原点是
重合,都是在左上角为(0,0)
设备坐标原点对应逻辑(0,0)
BOOL SetViewportOrgEx(
HDC hdc, // DC句柄
int X, // X位置设备坐标系
int Y, // Y位置设备坐标系
LPPOINT lpPoint //旧的坐标原点
);
逻辑坐标原点对应设备(0,0)
BOOL SetWindowOrgEx(
HDC hdc, // DC句柄
int X, // X位置,逻辑坐标系
int Y, // Y位置,逻辑坐标系
LPPOINT lpPoint //旧的坐标原点
);
二 文字和字体
1 文字绘制
Textout
int DrawText(
HDC hDC, //DC句柄
LPCTSTR lpString, //字符串
int nCount, //字符串长度
LPRECT lpRect,//绘制的矩形区域
UINT uFormat //绘制的方式
);
BOOL ExtTextOut(
HDC hdc, //DC句柄
int X, //X坐标
int Y, //Y坐标
UINT fuOptions, //输出选项
CONST RECT *lprc, //剪切矩形
LPCTSTR lpString, //字符串
UINT cbCount, //字符串的长度
CONST INT *lpDx //字符间距的数组
);
2 字符绘制属性
设置文字颜色
COLORREF SetTextColor(
HDC hdc, //DC句柄
COLORREF crColor //文字颜色
); 返回原来的颜色
设置文字的背景色
COLORREF SetBkColor(
HDC hdc, //DC句柄 handle of device context
COLORREF crColor //文字背景颜色
); 返回原来的背景颜色
设置背景绘制模式
int SetBkMode(
HDC hdc, //DC句柄
int iBkMode //背景绘制模式
); 返回原来的背景绘制模式
3 字体
Windows经常使用的字体是TrueType字体。
3.1 获取字体
HFONT CreateFont(
int nHeight, //字体的高
int nWidth, //字体的宽
int nEscapement, //字符串倾斜角度
int nOrientation, //字的旋转角度
int fnWeight, //黑体
DWORD fdwItalic, //斜体
DWORD fdwUnderline, //下划线
DWORD fdwStrikeOut,//删除线
DWORD fdwCharSet, //字符集
DWORD fdwOutputPrecision, //输出精度
DWORD fdwClipPrecision, //剪切精度
DWORD fdwQuality, //输出质量
DWORD fdwPitchAndFamily, //匹配字体
LPCTSTR lpszFace //字体名称
);
3.2 字体的使用
3.2.1 获取字体
3.2.2 放入DC
SelectObject
3.2.3 绘制文字
3.2.4 取出字体
SelectObject
3.2.5 删除字体
DeleteObject
二 对话框
1 对话框的分类
1.1 模式对话框 - 显示后,所在的应用程序的
其他窗口,无法接受输入(键盘、鼠标)。
1.2 无模式对话框 - 显示后,所在的应用程序
其他窗口可以获得输入焦点,接受输入。
2 对话框的使用方式
2.1 定义对话框资源
2.2 注册对话框窗口(可选)
2.3 创建和显示对话框
2.4 消息处理
2.5 对话框的结束
3 模式对话框
3.1 定义对话框资源
3.2 定义对话框的窗口处理函数
BOOL CALLBACK DialogProc(
HWND hwndDlg, // handle to dialog box
UINT uMsg, // message
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
); 返回值为0,表示没有处理相应的消息。
3.3 创建和显示对话框
int DialogBox(
HINSTANCE hInstance, //应用程序实例句柄
LPCTSTR lpTemplate,//对话框资源ID
HWND hWndParent, //父窗口
DLGPROC lpDialogFunc //对话框窗口处理函数
);返回执行结果
阻塞函数,一直等候对话框的结束。
3.4 消息处理
WM_INITDIALOG - 对话框创建成功之后(包括
对话框上的子控件),在对话框显示之前。
我们可以实现初始化数据的操作。
3.5 结束对话框
BOOL EndDialog(
HWND hDlg, //窗口句柄
int nResult //DialogBox函数的返回值
);
4 无模式对话框
4.1 定义对话框资源
4.2 定义对话框的窗口处理函数
4.3 创建对话框
HWND CreateDialog(
HINSTANCE hInstance, //应用程序实例句柄
LPCTSTR lpTemplate, //对话框资源ID
HWND hWndParent, //父窗口
DLGPROC lpDialogFunc //对话框窗口处理函数
); 返回创建好的窗口句柄
非阻塞函数,创建之后立刻返回。
4.4 显示对话框
ShowWindow
4.5 消息处理
WM_INITDIALOG
4.6 结束对话框
DestroyWindow
5 对话框和普通窗口对比
5.1 创建方式不同:
普通窗口 CreateWindow/Ex
对话框 DialogBox/CreateDialog
5.2 窗口处理函数不同
普通窗口 WindowProc,调用缺省处理函数
对话框 DialogProc,不需调用缺省处理函数
5.3 初始化消息不同
普通窗口 WM_CREATE
对话框 WM_INITDIALOG
//设置映射模式
g_nMap=MM_TEXT
int nOldMap = SetMapMode( hDC, g_nMap );
//绘图
//恢复旧的映射模式
SetMapMode( hDC, nOldMap );
//获取字体
HFONT hFont = CreateFont( 40, 10, 45, 0, FW_BLACK,
TRUE, TRUE, TRUE, 0, 0, 0, 0, 0, "隶书" );
//将字体放入DC
HFONT hOldFont = ( HFONT )
SelectObject( hDC, hFont );
//设置文字颜色
COLORREF nOldText =
SetTextColor( hDC, RGB( 50, 50, 200 ) );
//设置文字背景色
COLORREF nOldBack =
SetBkColor( hDC, RGB( 100, 100, 100 ) );
//设置背景模式
int nOldMode = SetBkMode( hDC, TRANSPARENT );
//绘制文字
CHAR szText[256] = "Hello Text long long long long";
TextOut( hDC, 100, 50, szText, strlen( szText ) );
SetTextColor( hDC, nOldText );
SetBkColor( hDC, nOldBack );
SetBkMode( hDC, nOldMode );
//取出字体
SelectObject( hDC, hOldFont );
//删除字体
DeleteObject( hFont );
对话框窗口处理函数
WM_INITDIALOG
WM_SYSCOMMAND
//创建和显示模式对话框
int nRet = DialogBox( g_hInst,
MAKEINTRESOURCE(IDD_MODAL),
hWnd, ModalProc );
ModalProc是对话框窗口处理函数
BOOL CALLBACK ModalProc( HWND hWnd,
UINT nMsg,
WPARAM wParam,
LPARAM lParam )
//创建无模式对话框
//创建和显示模式对话框
//创建无模式对话框
HWND hDialog = CreateDialog( g_hInst,
MAKEINTRESOURCE(IDD_MODELESS),
hWnd, ModelessProc );
//显示对话框窗口
ShowWindow( hDialog, SW_SHOW );
===============================day09========================================================================================================
一 Windows控件
1 Windows控件
Windows已经定义好的窗口类型,例如静态框、
按钮、文本编辑框等。
2 控件的使用
使用CreateWindow/CreateWindowEx创建,处理
控件消息。
3 控件的消息
通过消息设置或获取控件状态和信息。
通过消息响应按钮的处理(通知消息 - WM_COMMAND)。
二 静态框
1 静态框
静态框 - 窗口类的名称 STATIC,可以在窗口上
显示文字或图片。
从风格上分类:
显示文字 - SS_SIMPLE
显示图片 - SS_ICON/SS_BITMAP
2 静态框的使用
2.1 创建静态框
CreateWindow/CreateWindowEx
创建显示图片的静态框时,窗口名称要设置成
图片的ID号,格式为“#ID”。
2.2 静态框的消息处理
通过控件ID获取控件的窗口句柄
HWND GetDlgItem(
HWND hDlg, //父窗口句柄
int nIDDlgItem //控件ID
); 返回控件的窗口句柄
使用SendMessage 发送控件消息,修改或获取
控件的状态。
WM_SETICON - 设置新的ICON
...
2.3 消息响应
STN_CLICKED - 控件被点击的消息。
当控件被点击后,向它的父窗口发送
WM_COMMAND消息,同时将STN_CLICKED消息ID、
控件ID和控件窗口句柄发送给发送给父窗口。
三 按钮
1 按钮的分类
按钮的窗口类名称 “BUTTON”
3.1.1 下压式按钮
BS_PUSHBUTTON/BS_DEFPUSHBUTTON
3.1.2 单选按钮
BS_RADIOBUTTON/BS_AUTORADIOBUTTON
3.1.3 复选按钮
BS_CHECKBOX/BS_AUTOCHECKBOX
BS_3STATE/BS_AUTO3STATE
3.1.4 分组框
BS_GROUPBOX
2 下压式按钮
3.2.1 创建CreateWindow
3.2.2 消息处理
3.2.3 通知消息
BN_CLICKED - 当单击按钮,通知父窗口。
3 单选按钮
3.3.1 创建CreateWindow
BS_AUTORADIOBUTTON - 可以自动完成选择
BS_RADIOBUTTON - 需要手动完成选择
单选框的分组可以使用WS_GROUP风格。
在需要分组的第一个选项上,添加WS_GROUP风格。
3.3.2 消息处理
BM_SETCHECK
BM_GETCHECK
......
3.3.3 通知消息
BN_CLICKED - 当单击按钮,通知父窗口。
......
4 复选按钮
3.4.1 创建CreateWindow
BS_CHECKBOX - 需要手动完成选择
BS_AUTOCHECKBOX - 可以自动完成选择
BS_3STATE/BS_AUTO3STATE
3.4.2 消息处理
BM_SETCHECK
BM_GETCHECK
......
3.4.3 通知消息
BN_CLICKED - 当单击按钮,通知父窗口。
......
5 分组框
美观,增加交互界面的友好性
5.1 创建CreateWindow
使用BS_GROUPBOX风格
四 文本编辑框
1 文本编辑框分类
1.1 单行编辑框 - 默认单行
1.2 多行编辑框 - ES_MULTILINE
1.3 密码编辑框 - ES_PASSWORD
2 文本编辑框的使用
2.1 创建 CreateWindow
窗口类名称 - “EDIT”
2.2 控件消息
2.3 通知消息
EN_CHANGE - 当编辑框内的文本内容发生变化
将会向父窗口发送EN_CHANGE通知消息。
// WinStatic.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
#include "stdio.h"
#include "resource.h"
HINSTANCE g_hInst = NULL;
HWND g_hStatic = NULL;
HANDLE g_hStdOutput = NULL;
HICON g_hIcon[2] = { NULL };
void OnCreate( HWND hWnd )
{ //创建文字的静态框
CreateWindowEx( 0, "STATIC", "Hello Static",
WS_CHILD|WS_VISIBLE|SS_CENTER|SS_SUNKEN|SS_NOTIFY,
100, 100, 200, 150,
hWnd, (HMENU)1001, g_hInst, NULL );
//创建图片的静态框
g_hStatic = CreateWindowEx( 0, "STATIC", "#101",
WS_CHILD|WS_VISIBLE|SS_ICON|SS_SUNKEN|SS_NOTIFY,
300, 100, 400, 150,
hWnd, (HMENU)1002, g_hInst, NULL );
//加载图标
g_hIcon[0] = LoadIcon(
g_hInst, MAKEINTRESOURCE( IDI_ICON1 ) );
g_hIcon[1] = LoadIcon(
g_hInst, MAKEINTRESOURCE( IDI_ICON2 ) );
}
void SwtichIcon( HWND hWnd )
{
static int nColor = 0;
//获取控件的窗口句柄
HWND hChild = GetDlgItem( hWnd, 1002 );
//设置图标
if( 0 == nColor )
{
SendMessage( hChild, STM_SETICON,
(WPARAM)g_hIcon[0], 0 );
nColor = 1;
}
else
{
SendMessage( hChild, STM_SETICON,
(WPARAM)g_hIcon[1], 0 );
nColor = 0;
}
}
void OnLButtonDown( HWND hWnd )
{
SwtichIcon( hWnd );
}
void OnCommand( HWND hWnd, WPARAM wParam, LPARAM lParam )
{
int nNotifyCode = HIWORD( wParam );
int nID = LOWORD( wParam );
CHAR szText[256] = { 0 };
sprintf( szText,
"WM_COMMAND: NotifyCode=%d, ID=%d\n",
nNotifyCode, nID );
WriteConsole( g_hStdOutput, szText,
strlen(szText), NULL, NULL );
switch( nID )
{
case 1001:
break;
case 1002:
switch( nNotifyCode)
{
case STN_CLICKED:
SwtichIcon( hWnd );
break;
}
break;
}
}
LRESULT CALLBACK WndProc( HWND hWnd,
UINT nMsg,
WPARAM wParam,
LPARAM lParam )
{
switch( nMsg )
{
case WM_CREATE:
OnCreate( hWnd );
break;
case WM_LBUTTONDOWN:
OnLButtonDown( hWnd );
break;
case WM_COMMAND:
OnCommand( hWnd, wParam, lParam );
break;
case WM_DESTROY:
PostQuitMessage( 0 );
break;
}
return DefWindowProc( hWnd, nMsg, wParam, lParam );
}
BOOL RegisterWnd( LPSTR pszClassName )
{
WNDCLASSEX wce = { 0 };
wce.cbSize = sizeof( wce );
wce.style = CS_HREDRAW|CS_VREDRAW;
wce.cbClsExtra = 0;
wce.cbWndExtra = 0;
wce.hInstance = g_hInst;
wce.lpfnWndProc = WndProc;
wce.hIcon = NULL;
wce.hIconSm = NULL;
wce.hCursor = NULL;
wce.hbrBackground = (HBRUSH)( COLOR_WINDOW );
wce.lpszMenuName = NULL;
wce.lpszClassName = pszClassName;
ATOM nAtom = RegisterClassEx( &wce );
if( 0 == nAtom )
{
return FALSE;
}
return TRUE;
}
HWND CreateWnd( LPSTR pszClassName )
{
HWND hWnd = CreateWindowEx( 0, pszClassName,
"MyWnd", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, g_hInst, NULL );
return hWnd;
}
void DisplayWnd( HWND hWnd )
{
ShowWindow( hWnd, SW_SHOW );
UpdateWindow( hWnd );
}
void Message( )
{
MSG msg = { 0 };
while( GetMessage( &msg, NULL, 0, 0 ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
}
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
AllocConsole( );
g_hStdOutput = GetStdHandle( STD_OUTPUT_HANDLE );
g_hInst = hInstance;
RegisterWnd( "MYWND" );
HWND hWnd = CreateWnd( "MYWND" );
DisplayWnd( hWnd );
Message( );
return 0;
}
下压式按钮
// WinButton.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
HINSTANCE g_hInst = NULL;
void OnCreate( HWND hWnd )
{
//创建下压式按钮
CreateWindowEx( 0, "BUTTON", "PushButton",
WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,
100, 100, 100, 40,
hWnd, (HMENU)1001, g_hInst, NULL );
}
void OnCommand( HWND hWnd, WPARAM wParam, LPARAM lParam )
{
int nNotifyCode = HIWORD( wParam );
int nID = LOWORD( wParam );
switch( nID )
{
case 1001:
switch( nNotifyCode )
{
case BN_CLICKED:
MessageBox( NULL, "Hello Button",
"WinButton", MB_OK );
EnableWindow( (HWND)lParam, FALSE );
break;
}
break;
}
}
LRESULT CALLBACK WndProc( HWND hWnd,
UINT nMsg,
WPARAM wParam,
LPARAM lParam )
{
switch( nMsg )
{
case WM_DESTROY:
PostQuitMessage( 0 );
break;
case WM_CREATE:
OnCreate( hWnd );
break;
case WM_COMMAND:
OnCommand( hWnd, wParam, lParam );
break;
}
return DefWindowProc( hWnd, nMsg, wParam, lParam );
}
BOOL RegisterWnd( LPSTR pszClassName )
{
WNDCLASSEX wce = { 0 };
wce.cbSize = sizeof( wce );
wce.style = CS_HREDRAW|CS_VREDRAW;
wce.cbClsExtra = 0;
wce.cbWndExtra = 0;
wce.hInstance = g_hInst;
wce.lpfnWndProc = WndProc;
wce.hIcon = NULL;
wce.hIconSm = NULL;
wce.hCursor = NULL;
wce.hbrBackground = (HBRUSH)( COLOR_WINDOW );
wce.lpszMenuName = NULL;
wce.lpszClassName = pszClassName;
ATOM nAtom = RegisterClassEx( &wce );
if( 0 == nAtom )
{
return FALSE;
}
return TRUE;
}
HWND CreateWnd( LPSTR pszClassName )
{
HWND hWnd = CreateWindowEx( 0, pszClassName,
"MyWnd", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, g_hInst, NULL );
return hWnd;
}
void DisplayWnd( HWND hWnd )
{
ShowWindow( hWnd, SW_SHOW );
UpdateWindow( hWnd );
}
void Message( )
{
MSG msg = { 0 };
while( GetMessage( &msg, NULL, 0, 0 ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
}
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
g_hInst = hInstance;
RegisterWnd( "MYWND" );
HWND hWnd = CreateWnd( "MYWND" );
DisplayWnd( hWnd );
Message( );
return 0;
}
编辑框
void OnCreate( HWND hWnd )
{
CreateWindowEx( 0, "EDIT", "",
WS_CHILD|WS_VISIBLE|
WS_HSCROLL|WS_VSCROLL|ES_MULTILINE|
ES_AUTOHSCROLL|ES_AUTOVSCROLL,
0, 0, 100, 200,
hWnd, (HMENU)1001, g_hInst, NULL );
}
void OnSize( HWND hWnd, WPARAM wParam, LPARAM lParam )
{
int nWidth = LOWORD( lParam );
int nHeight= HIWORD( lParam );
HWND hEdit = GetDlgItem( hWnd, 1001 );
if( NULL != hEdit )
{
MoveWindow( hEdit, 0, 0, nWidth,
nHeight, TRUE );
}
}
void OnSave( HWND hWnd )
{
HWND hEdit = GetDlgItem( hWnd, ID_EDITWND );
//获取EDIT窗口的数据长度
LRESULT nTextLen =
SendMessage( hEdit, WM_GETTEXTLENGTH, 0, 0 );
LPSTR pszText = (LPSTR)malloc( nTextLen + 1 );
memset( pszText, 0, nTextLen+1 );
//获取EDIT窗口的数据内容
SendMessage( hEdit, WM_GETTEXT,
(WPARAM)nTextLen, (LPARAM)pszText );
//保存文件
FILE * pFile = fopen( "c:\\myedit.txt", "w+" );
fwrite( pszText, nTextLen, 1, pFile );
fclose( pFile );
//释放内存
free( pszText );
}
case ID_FONT:
{
HFONT hFont = CreateFont( 40, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, "宋体");
HWND hEdit = GetDlgItem( hWnd, ID_EDITWND );
SendMessage( hEdit, WM_SETFONT,
(WPARAM)hFont, MAKELPARAM( TRUE, 0 ) );
==============================day10=========================================================================================================
一 组合框
1 组合框样式
1.1 简单组合框 - CBS_SIMPLE
1.2 下拉式组合框 - CBS_DROPDOWN
1.3 下拉列表式组合框 - CBS_DROPDOWNLIST
2 组合框的使用
2.1 创建
窗口类名称 - COMBOBOX
2.2 控件消息
2.2.1 添加选项
CB_ADDSTRING - 追加
CB_INSERTSTRING - 插入到指定位置
2.2.2 选择和获取
CB_SETCURSEL
CB_GETCURSEL
CB_SELECTSTRING
不区分大小写,从左到右字符串匹配。
2.2.3 清空和删除
CB_DELETESTRING - 删除指定项
CB_RESETCONTENT - 清空所有内容
2.2.4 查找
CB_FINDSTRING - 查找项
CB_FINDSTRINGEXACT - 查找项
2.2.5 获取选项内容
CB_GETLBTEXT - 获取内容
CB_GETLBTEXTLEN - 长度
2.2.6 列出目录
CB_DIR - 列出指定路径下的子目录或者文件。
2.2.7 选项数据
CB_SETITEMDATA - 将数据保存到选项
CB_GETITEMDATA - 从选项中取数据
2.3 通知消息
CBN_SELCHANGE - 当选择的项发生变化后,通知
父窗口。
二 列表框
1 列表框的样式
1.1 单列 - 默认
1.2 多列 - LBS_MULTICOLUMN
2 列表框的使用
2.1 创建
窗口类名称 - LISTBOX
2.2 控件消息
2.2.1 添加项
LB_ADDSTRING/LB_INSERTSTRING
2.2.2 删除项
LB_RESETCONTENT 清空
LB_DELETESTRING 删除
2.2.3 设置和获取选择项
LB_GETCURSEL
LB_SETCURSEL
LB_GETSEL
LB_GETSELCOUNT
LB_GETSELITEMS
2.2.4 查找
LB_FINDSTRING
2.2.5 获取选项内容
LB_GETTEXT
LB_GETTEXTLEN
2.2.6 列出目录
LB_DIR
2.2.7 选项数据
LB_SETITEMDATA
LB_GETITEMDATA
2.3 通知消息
需要增加 LBS_NOTIFY 风格。
LBN_SELCHANGE - 选项变化时,通知父窗口
三 滚动条
1 滚动条的样式
1.1 水平滚动条 - SBS_HORZ
1.2 垂直滚动条 - SBS_VERT
2 滚动条的使用
2.1 创建
窗口类名称 - SCROLLBAR
2.2 控件消息
2.2.1 滚动条的范围
SBM_GETRANGE - 获取滚动条范围
SBM_SETRANGE - 设置滚动条范围
2.2.2 滑块位置
SBM_SETPOS - 设置位置
SBM_GETPOS - 获取位置
2.2.3 设置或获取滚动条信息
SBM_SETSCROLLINFO - 设置
SBM_GETSCROLLINFO - 获取
2.3 通知消息
不使用WM_CAOMMAND作为通知消息,而是使用
父窗口消息:
WM_HSCROLL - 水平
WM_VSCROLL - 垂直
void OnCreate( HWND hWnd )
{ //创建简单组合框
CreateWindowEx( 0, "COMBOBOX", "SIMPLE",
WS_CHILD|WS_VISIBLE|CBS_SIMPLE,
50, 100, 140, 200,
hWnd, (HMENU)1001, g_hInst, NULL );
//创建下拉式组合框
CreateWindowEx( 0, "COMBOBOX", "DROPDOWN",
WS_CHILD|WS_VISIBLE|CBS_DROPDOWN,
200, 100, 140, 200,
hWnd, (HMENU)1002, g_hInst, NULL );
//创建下拉列表式组合框
CreateWindowEx( 0, "COMBOBOX", "DROPLIST",
WS_CHILD|WS_VISIBLE|CBS_DROPDOWNLIST,
350, 100, 140, 200,
hWnd, (HMENU)1003, g_hInst, NULL );
}
void OnAddString( HWND hWnd )
{
HWND hSimple = GetDlgItem( hWnd, 1001 );
HWND hDropDown = GetDlgItem( hWnd, 1002 );
HWND hDropList = GetDlgItem( hWnd, 1003 );
for( int nIndex=0; nIndex<10; nIndex++ )
{
CHAR szText[256] = { 0 };
sprintf( szText, "Hello Combo %d", nIndex );
//在组合框中添加选项
SendMessage( hSimple, CB_ADDSTRING, 0,
(LPARAM)szText );
SendMessage( hDropDown, CB_ADDSTRING, 0,
(LPARAM)szText );
SendMessage( hDropList, CB_ADDSTRING, 0,
(LPARAM)szText );
}
//使用索引设置选择项
SendMessage( hSimple, CB_SETCURSEL, 0, 0 );
SendMessage( hDropDown, CB_SETCURSEL, 0, 0 );
SendMessage( hDropList, CB_SETCURSEL, 0, 0 );
//使用字符串设置选择项
CHAR szSel[256] = "hello Combo 8";
SendMessage( hDropList, CB_SELECTSTRING, 0,
(LPARAM)szSel );
}
void OnEmpty( HWND hWnd )
{
HWND hSimple = GetDlgItem( hWnd, 1001 );
HWND hDropDown = GetDlgItem( hWnd, 1002 );
HWND hDropList = GetDlgItem( hWnd, 1003 );
//清空所有选项
SendMessage( hSimple, CB_RESETCONTENT, 0, 0 );
SendMessage( hDropDown, CB_RESETCONTENT, 0, 0 );
SendMessage( hDropList, CB_RESETCONTENT, 0, 0 );
}
void OnDelete( HWND hWnd )
{
HWND hSimple = GetDlgItem( hWnd, 1001 );
HWND hDropDown = GetDlgItem( hWnd, 1002 );
HWND hDropList = GetDlgItem( hWnd, 1003 );
//获取当前的选择项
int nSel = SendMessage( hSimple, CB_GETCURSEL, 0, 0 );
if( CB_ERR != nSel )
{ //删除指定的选项
SendMessage( hSimple, CB_DELETESTRING, nSel, 0 );
}
nSel = SendMessage( hDropDown, CB_GETCURSEL, 0, 0 );
if( CB_ERR != nSel )
{
SendMessage( hDropDown, CB_DELETESTRING, nSel, 0 );
}
nSel = SendMessage( hDropList, CB_GETCURSEL, 0, 0 );
if( CB_ERR != nSel )
{
SendMessage( hDropList, CB_DELETESTRING, nSel, 0 );
}
}
void OnFind( HWND hWnd )
{
HWND hSimple = GetDlgItem( hWnd, 1001 );
HWND hDropDown = GetDlgItem( hWnd, 1002 );
HWND hDropList = GetDlgItem( hWnd, 1003 );
//查找字符串获取其选项索引号
CHAR szSerach[256] = "hello combo 1";
int nIndex = SendMessage( hSimple,
CB_FINDSTRING, 0, (LPARAM)szSerach );
SendMessage( hDropDown, CB_SETCURSEL, nIndex, 0 );
SendMessage( hDropList, CB_SETCURSEL, nIndex, 0 );
}
void OnContent( HWND hWnd )
{
HWND hSimple = GetDlgItem( hWnd, 1001 );
HWND hDropDown = GetDlgItem( hWnd, 1002 );
HWND hDropList = GetDlgItem( hWnd, 1003 );
int nSel = SendMessage( hSimple, CB_GETCURSEL, 0, 0 );
if( CB_ERR == nSel )
{
return;
}
//获取选项内容
CHAR szText[256] = { 0 };
SendMessage( hSimple, CB_GETLBTEXT, nSel,
( LPARAM )szText );
//
SendMessage( hDropDown, CB_SELECTSTRING, 0,
(LPARAM)szText );
SendMessage( hDropList, CB_SELECTSTRING, 0,
(LPARAM)szText );
}
void OnCommand( HWND hWnd, WPARAM wParam, LPARAM lParam )
{
int nNotifyCode = HIWORD( wParam );
int nID = LOWORD( wParam );
switch( nID )
{
case ID_ADDSTRING:
OnAddString( hWnd );
break;
case ID_DELETE:
OnDelete( hWnd );
break;
case ID_EMPTY:
OnEmpty( hWnd );
break;
case ID_FIND:
OnFind( hWnd );
break;
case ID_CONTENT:
OnContent( hWnd );
break;
}
}
void OnPath( HWND hWnd )
{
HWND hSimple = GetDlgItem( hWnd, 1001 );
HWND hDropDown = GetDlgItem( hWnd, 1002 );
HWND hDropList = GetDlgItem( hWnd, 1003 );
//显示指定目录下的文件和子目录
CHAR szPath[256] = "c:\\*.*";
SendMessage( hSimple, CB_DIR,
DDL_ARCHIVE|DDL_DIRECTORY, (LPARAM)szPath );
SendMessage( hDropDown, CB_DIR,
DDL_ARCHIVE|DDL_DIRECTORY, (LPARAM)szPath );
SendMessage( hDropList, CB_DIR,
DDL_ARCHIVE|DDL_DIRECTORY, (LPARAM)szPath );
}
void OnInfo( HWND hWnd )
{
HWND hSimple = GetDlgItem( hWnd, 1001 );
HWND hDropDown = GetDlgItem( hWnd, 1002 );
HWND hDropList = GetDlgItem( hWnd, 1003 );
//获取选择项
int nSel = SendMessage( hSimple,
CB_GETCURSEL, 0, 0 );
if( CB_ERR == nSel )
{
return;
}
//取出数据
int nValue = SendMessage( hSimple,
CB_GETITEMDATA, nSel, 0 );
CHAR szText[256] = { 0 };
sprintf( szText, "%d: %d", nSel, nValue );
MessageBox( NULL, szText, "WinCombo", MB_OK );
}
void OnCreate( HWND hWnd )
{ //单列的列表框
CreateWindowEx( WS_EX_CLIENTEDGE,
"LISTBOX", "SINGLE",
WS_CHILD|WS_VISIBLE|WS_HSCROLL|
WS_VSCROLL|LBS_NOTIFY,
100, 100, 200, 200,
hWnd, (HMENU)1001, g_hInst, NULL );
//多列的列表框
CreateWindowEx( WS_EX_CLIENTEDGE,
"LISTBOX", "SINGLE",
WS_CHILD|WS_VISIBLE|WS_HSCROLL|
WS_VSCROLL|LBS_MULTICOLUMN|LBS_MULTIPLESEL,
350, 100, 200, 200,
hWnd, (HMENU)1002, g_hInst, NULL );
}
滚动条
// WinScroll.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
HINSTANCE g_hInst = NULL;
HWND g_hHorz = NULL;
HWND g_hVert = NULL;
void OnCreate( HWND hWnd )
{ //水平滚动条
g_hHorz = CreateWindowEx( 0, "SCROLLBAR", "HORZ",
WS_CHILD|WS_VISIBLE|SBS_HORZ,
0, 200, 200, 20,
hWnd, (HMENU)1001, g_hInst, NULL );
//垂直滚动条
g_hVert = CreateWindowEx( 0, "SCROLLBAR", "VERT",
WS_CHILD|WS_VISIBLE|SBS_VERT,
200, 0, 20, 200,
hWnd, (HMENU)1002, g_hInst, NULL );
//设置滚动条滚动范围
SendMessage( g_hHorz, SBM_SETRANGE, 0, 200 );
SendMessage( g_hVert, SBM_SETRANGE, 0, 200 );
SendMessage( g_hHorz, SBM_SETPOS, 100, TRUE );
}
void OnHScroll( HWND hWnd, WPARAM wParam, LPARAM lParam )
{
int nScrollCode = LOWORD( wParam );
int nPos = HIWORD( wParam );
HWND hCtrl = (HWND)lParam;
switch( nScrollCode )
{
case SB_LINELEFT:
nPos = SendMessage( hCtrl, SBM_GETPOS, 0, 0 );
nPos--;
SendMessage( hCtrl, SBM_SETPOS, nPos, TRUE );
break;
case SB_LINERIGHT:
nPos = SendMessage( hCtrl, SBM_GETPOS, 0, 0 );
nPos++;
SendMessage( hCtrl, SBM_SETPOS, nPos, TRUE );
break;
case SB_PAGELEFT:
nPos = SendMessage( hCtrl, SBM_GETPOS, 0, 0 );
nPos -= 10;
SendMessage( hCtrl, SBM_SETPOS, nPos, TRUE );
break;
case SB_PAGERIGHT:
nPos = SendMessage( hCtrl, SBM_GETPOS, 0, 0 );
nPos += 10;
SendMessage( hCtrl, SBM_SETPOS, nPos, TRUE );
break;
case SB_THUMBTRACK: //滑块拖拽过程中
SendMessage( hCtrl, SBM_SETPOS, nPos, TRUE );
break;
case SB_THUMBPOSITION: //滑块拖拽结束
SendMessage( hCtrl, SBM_SETPOS, nPos, TRUE );
break;
}
InvalidateRect( hWnd, NULL, TRUE );
}
void OnVScroll( HWND hWnd, WPARAM wParam, LPARAM lParam )
{
int nScrollCode = LOWORD( wParam );
int nPos = HIWORD( wParam );
HWND hCtrl = (HWND)lParam;
switch( nScrollCode )
{
case SB_LINEUP:
nPos = SendMessage( hCtrl, SBM_GETPOS, 0, 0 );
nPos--;
SendMessage( hCtrl, SBM_SETPOS, nPos, TRUE );
break;
case SB_LINEDOWN:
nPos = SendMessage( hCtrl, SBM_GETPOS, 0, 0 );
nPos++;
SendMessage( hCtrl, SBM_SETPOS, nPos, TRUE );
break;
case SB_PAGEUP:
nPos = SendMessage( hCtrl, SBM_GETPOS, 0, 0 );
nPos -= 10;
SendMessage( hCtrl, SBM_SETPOS, nPos, TRUE );
break;
case SB_PAGEDOWN:
nPos = SendMessage( hCtrl, SBM_GETPOS, 0, 0 );
nPos += 10;
SendMessage( hCtrl, SBM_SETPOS, nPos, TRUE );
break;
case SB_THUMBTRACK: //滑块拖拽过程中
SendMessage( hCtrl, SBM_SETPOS, nPos, TRUE );
break;
case SB_THUMBPOSITION: //滑块拖拽结束
SendMessage( hCtrl, SBM_SETPOS, nPos, TRUE );
break;
}
InvalidateRect( hWnd, NULL, TRUE );
}
void OnPaint( HWND hWnd )
{
PAINTSTRUCT ps = { 0 };
HDC hDC = BeginPaint( hWnd, &ps );
//获取水平和垂直滚动条的位置
int nXPos = SendMessage( g_hHorz, SBM_GETPOS, 0, 0 );
int nYPos = SendMessage( g_hVert, SBM_GETPOS, 0, 0 );
//输出字符
CHAR szText[] = "Hello Scroll Bar";
TextOut( hDC, 100-nXPos, 100-nYPos,
szText, strlen( szText ) );
EndPaint( hWnd, &ps );
}
LRESULT CALLBACK WndProc( HWND hWnd,
UINT nMsg,
WPARAM wParam,
LPARAM lParam )
{
switch( nMsg )
{
case WM_DESTROY:
PostQuitMessage( 0 );
break;
case WM_CREATE:
OnCreate( hWnd );
break;
case WM_HSCROLL:
OnHScroll( hWnd, wParam, lParam );
break;
case WM_VSCROLL:
OnVScroll( hWnd, wParam, lParam );
break;
case WM_PAINT:
OnPaint( hWnd );
break;
}
return DefWindowProc( hWnd, nMsg, wParam, lParam );
}
BOOL RegisterWnd( LPSTR pszClassName )
{
WNDCLASSEX wce = { 0 };
wce.cbSize = sizeof( wce );
wce.style = CS_HREDRAW|CS_VREDRAW;
wce.cbClsExtra = 0;
wce.cbWndExtra = 0;
wce.hInstance = g_hInst;
wce.lpfnWndProc = WndProc;
wce.hIcon = NULL;
wce.hIconSm = NULL;
wce.hCursor = NULL;
wce.hbrBackground = (HBRUSH)( COLOR_WINDOW );
wce.lpszMenuName = NULL;
wce.lpszClassName = pszClassName;
ATOM nAtom = RegisterClassEx( &wce );
if( 0 == nAtom )
{
return FALSE;
}
return TRUE;
}
HWND CreateWnd( LPSTR pszClassName )
{
HWND hWnd = CreateWindowEx( 0, pszClassName,
"MyWnd", WS_OVERLAPPEDWINDOW|WS_VSCROLL|WS_HSCROLL,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, g_hInst, NULL );
return hWnd;
}
void DisplayWnd( HWND hWnd )
{
ShowWindow( hWnd, SW_SHOW );
UpdateWindow( hWnd );
}
void Message( )
{
MSG msg = { 0 };
while( GetMessage( &msg, NULL, 0, 0 ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
}
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
g_hInst = hInstance;
RegisterWnd( "MYWND" );
HWND hWnd = CreateWnd( "MYWND" );
DisplayWnd( hWnd );
Message( );
return 0;
}
============================================day11==========================================================================================
一 Windows 库程序
1 Windows 库程序
1.1 作用
可以方便项目分工、提高代码的重用。
1.2 库的分类
1.2.1 静态库 - 程序执行时,不需要库存在。
库中的代码被链接到程序当中。
文件扩展名: LIB
1.2.2 动态库 - 程序执行时,库必须存在,
库中的代码和程序是不同的文件。
文件扩展名: DLL
2 静态库
2.1 C和静态库
2.1.1 创建库
2.1.2 实现库函数
添加扩展名为.C的文件和相应的函数。
2.1.3 使用库函数
库的导入:
1)使用项目的Setting中Link的设置
2)使用 #pragma, 例如
#pragma comment( lib, "../lib/winclib.lib")
直接调用库中的函数即可。
2.2 C++和静态库
2.2.1 创建库
2.2.2 实现库函数
添加扩展名为.CPP的文件和相应的函数。
2.2.3 使用库函数
1) 库的导入
2) 定义函数原型
2.2.4 C++中使用C库函数
需要在定义函数原型时,增加extern “C”
例如:
extern "C" {
int C_Add( int nAdd1, int nAdd2 );
}
extern "C" int C_Sub( int nSub1, int nSub2 );
3 动态库
3.1 动态库
3.1.1 函数
3.1.2 变量
3.1.3 类
3.2 动态库函数
3.2.1 库的创建
3.2.2 库的实现
1)函数的实现
2)函数的导出
1 _declspec( dllexport )
2 extern “C” _declspec( dllexport )
3 使用DEF文件导出
项目中增加.def文件,将导出函数添加
在DEF中。
3)动态库的LIB文件不同与静态库。
3.2.3 库的使用 - 隐式链接
1)导入库
导入动态库的LIB文件。
2)定义函数原型
1 _declspec( dllimport )
2 对于使用extern “C”导出,必须也添加
extern “C”
3)使用库函数
4)DLL存放路径
程序搜索DLL时,查找路径
1 程序相同目录下
2 程序工作目录
3 Windows\System32
4 Windows\System
5 Windows 目录
6 环境变量 PATH 指定路径
3.2.3 库的使用 - 显式链接
1)加载动态库
HINSTANCE LoadLibrary(
LPCTSTR lpLibFileName //动态库全路径
); 返回加载成功DLL的句柄
2)获取函数
FARPROC GetProcAddress(
HMODULE hModule, //DLL句柄
LPCSTR lpProcName //函数名称
); 返回函数指针
使用 __declspec( dllexport ) 导出的函数,
无法按照函数名获取。
使用extern “C” 或者 DEF 方式可以正常获取。
3)使用函数
4)卸载动态库
BOOL FreeLibrary(
HMODULE hLibModule //DLL句柄
);
卸载之后,函数指针不能继续使用。
3.2.4 隐式和显式链接
1)隐式 - 需要导入LIB
显示 - 需要DLL路径
2)隐式 - DLL随着EXE启动一起加载
显示 - 是在使用LoadLibrary函数时才加载
3)隐式 - 导入LIB发生变化,需要重新编译
显示 - 通过函数名匹配,不需修改
3.3 动态库变量
3.3.1 库建立
3.3.2 变量的导出
1) _declspec( dllexport )
2) DEF 文件
在定义导出变量时,要增加 DATA, 例如
g_nDllValue2 @1 DATA
3.3.3 变量的使用
1) DLL的导入LIB
2) 定义导入变量
3) 使用
3.4 动态库的类
3.4.1 库建立
3.4.2 类的导出
_declspec( dllexport )
例如: class DLLCLASSEXT CMath
#ifdef DLLCLASS_EXPORTS
#define DLLCLASSEXT _declspec( dllexport )
#else
#define DLLCLASSEXT _declspec( dllimport )
#endif
3.4.3 类的使用
1) DLL的导入LIB
2) 定义导入类
_declspec( dllimport )
3) 使用
3.5 动态库的入口函数
当加载DLL或卸载DLL执行入口函数。
BOOL WINAPI DllMain(
HINSTANCE hinstDLL, //DLL实例句柄
DWORD fdwReason,//动态库加载的原因
LPVOID lpvReserved //保留值
);成功TRUE
#pragma comment( lib, "../lib/winclib.lib")
=============================================day12==========================================================================================一 Windows文件系统
1 Windows文件系统
Windows常用的文件系统:
FAT16/FAT32 - 16位 -> 32位
NTFS - 微软推荐
CDFS - 光驱的文件系统
2 windows 卷(Volume)
2.1 Windows卷的获取
支持A-Z卷,A\B早期软驱
获取当前所有的逻辑驱动器的盘符
DWORD GetLogicalDriveStrings(
DWORD nBufferLength, //BUFF的大小
LPTSTR lpBuffer //BUFF的地址
);
DWORD GetLogicalDrives(VOID)
2.2 卷的类型
UINT GetDriveType(
LPCTSTR lpRootPathName //盘符
); 返回卷的类型
2.3 卷的大小
BOOL GetDiskFreeSpaceEx(
LPCTSTR lpDirectoryName, //盘符
PULARGE_INTEGER lpFreeBytesAvailableToCaller,
//可用的空余字节数
PULARGE_INTEGER lpTotalNumberOfBytes,
//全部的字节数
PULARGE_INTEGER lpTotalNumberOfFreeBytes
//全部的空余字节数
);
2.4 卷的信息
BOOL GetVolumeInformation(
LPCTSTR lpRootPathName,//盘符
LPTSTR lpVolumeNameBuffer, //存放卷标的BUFF
DWORD nVolumeNameSize, //卷标的BUFF长度
LPDWORD lpVolumeSerialNumber, //卷的序列号
LPDWORD lpMaximumComponentLength,//文件名称长度
LPDWORD lpFileSystemFlags, //文件系统标识’
LPTSTR lpFileSystemNameBuffer,
//存放文件系统名称的BUFF
DWORD nFileSystemNameSize
//名称的BUFF的长度
);
2.5 卷标的修改
BOOL SetVolumeLabel(
LPCTSTR lpRootPathName,//盘符
LPCTSTR lpVolumeName //卷标
);
2.6 簇
BOOL GetDiskFreeSpace(
LPCTSTR lpRootPathName,//盘符
LPDWORD lpSectorsPerCluster, //每簇的扇区数
LPDWORD lpBytesPerSector, //每扇区的字节数
LPDWORD lpNumberOfFreeClusters,
//空余簇的数量 pointer to number of free clusters
LPDWORD lpTotalNumberOfClusters
//全部簇的数量
);
簇 - 文件系统用来管理文件数据的最小单位。
每一个簇都是由连续的几个扇区组成,例如
通常是由1/2/4/8/16...扇区组成。
FAT16/32 - 4K、8K
NTFS - 4K
##################################################
void ShowInfo( LPSTR pszDrive )
{ //获取卷的信息
CHAR szVolumeName[256] = { 0 };
DWORD nVolumeSrieal = 0;
DWORD nFileLen = 0;
DWORD nFileSys = 0;
CHAR szFileSys[256] = { 0 };
GetVolumeInformation( pszDrive,
szVolumeName, 256,
&nVolumeSrieal, &nFileLen,
&nFileSys, szFileSys, 256 );
printf(
" INFO: VolumeName=%s VolumeSrieal=%08X"
" FileLen=%d FileSys=%s(%d)\n",
szVolumeName, nVolumeSrieal, nFileLen,
szFileSys, nFileSys );
}
void ShowSize( LPSTR pszDrive )
{ //获取硬盘大小
UINT64 nFreeAvailable = 0;
UINT64 nTotal = 0;
UINT64 nFree = 0;
GetDiskFreeSpaceEx( pszDrive,
(PULARGE_INTEGER)&nFreeAvailable,
(PULARGE_INTEGER)&nTotal,
(PULARGE_INTEGER)&nFree );
printf(
" SIZE: Available=%I64d Total=%I64d Free=%I64d\n",
nFreeAvailable >> 20,
nTotal >> 20, nFree >> 20 );
}
void ShowType( LPSTR pszDrive )
{ //获取卷的类型
UINT nType = GetDriveType( pszDrive );
switch( nType )
{
case DRIVE_FIXED:
printf( " Type: 硬盘\n" );
break;
case DRIVE_CDROM:
printf( " Type: 光驱\n" );
break;
}
}
void ShowVolume( )
{ //获取所有逻辑盘的盘符
CHAR szDrive[256] = { 0 };
GetLogicalDriveStrings( 256, szDrive );
DWORD nDrive = GetLogicalDrives( );
printf( "ALL Drive: %08X\n", nDrive );
//显示每个盘符
CHAR * pszDrive = szDrive;
while( pszDrive[0] != 0 )
{
printf( "%s\n", pszDrive );
//显示卷的类型
ShowType( pszDrive );
//显示卷的大小
ShowSize( pszDrive );
//显示卷的信息
ShowInfo( pszDrive );
pszDrive = pszDrive + strlen( pszDrive ) + 1;
}
}
int main(int argc, char* argv[])
{
ShowVolume( );
getch( );
return 0;
}
###############################################
void ShowCluster( LPSTR pszDrive )
{ //获取簇的信息
DWORD nSectorsPerCluster = 0;
DWORD nBytesPerSector = 0;
DWORD nNumberOfFreeClusters = 0;
DWORD nTotalNumberOfClusters = 0;
GetDiskFreeSpace( pszDrive,
&nSectorsPerCluster,
&nBytesPerSector,
&nNumberOfFreeClusters,
&nTotalNumberOfClusters );
printf( " CLUSTER: SectorsPerCluster=%d "
" BytesPerSector=%d FreeClusters=%d "
" TotalClusters=%d\n",
nSectorsPerCluster, nBytesPerSector,
nNumberOfFreeClusters,
nTotalNumberOfClusters );
}
void RenameVolume( LPSTR pszDrive )
{
//修改卷标
SetVolumeLabel( pszDrive, "MYWORK" );
}
void ShowInfo( LPSTR pszDrive )
{ //获取卷的信息
CHAR szVolumeName[256] = { 0 };
DWORD nVolumeSrieal = 0;
DWORD nFileLen = 0;
DWORD nFileSys = 0;
CHAR szFileSys[256] = { 0 };
GetVolumeInformation( pszDrive,
szVolumeName, 256,
&nVolumeSrieal, &nFileLen,
&nFileSys, szFileSys, 256 );
printf(
" INFO: VolumeName=%s VolumeSrieal=%08X"
" FileLen=%d FileSys=%s(%d)\n",
szVolumeName, nVolumeSrieal, nFileLen,
szFileSys, nFileSys );
}
void ShowSize( LPSTR pszDrive )
{ //获取硬盘大小
UINT64 nFreeAvailable = 0;
UINT64 nTotal = 0;
UINT64 nFree = 0;
GetDiskFreeSpaceEx( pszDrive,
(PULARGE_INTEGER)&nFreeAvailable,
(PULARGE_INTEGER)&nTotal,
(PULARGE_INTEGER)&nFree );
printf(
" SIZE: Available=%I64d Total=%I64d Free=%I64d\n",
nFreeAvailable >> 20,
nTotal >> 20, nFree >> 20 );
}
void ShowType( LPSTR pszDrive )
{ //获取卷的类型
UINT nType = GetDriveType( pszDrive );
switch( nType )
{
case DRIVE_FIXED:
printf( " Type: 硬盘\n" );
break;
case DRIVE_CDROM:
printf( " Type: 光驱\n" );
break;
}
}
void ShowVolume( )
{ //获取所有逻辑盘的盘符
CHAR szDrive[256] = { 0 };
GetLogicalDriveStrings( 256, szDrive );
DWORD nDrive = GetLogicalDrives( );
printf( "ALL Drive: %08X\n", nDrive );
//显示每个盘符
CHAR * pszDrive = szDrive;
while( pszDrive[0] != 0 )
{
printf( "%s\n", pszDrive );
//显示卷的类型
ShowType( pszDrive );
//显示卷的大小
ShowSize( pszDrive );
//显示卷的信息
ShowInfo( pszDrive );
//显示卷的大小(簇)
ShowCluster( pszDrive );
pszDrive = pszDrive + strlen( pszDrive ) + 1;
}
}
##################################
void GetDirectory( )
{
//获取Windows安装目录
CHAR szWindows[MAX_PATH] = { 0 };
GetWindowsDirectory( szWindows, MAX_PATH );
printf( "Windows Directory: %s\n", szWindows );
//获取系统目录System32
CHAR szSystem[MAX_PATH] = { 0 };
GetSystemDirectory( szSystem, MAX_PATH );
printf( "System Directory: %s\n", szSystem );
//获取临时文件目录
CHAR szTempPath[MAX_PATH] = { 0 };
GetTempPath( MAX_PATH, szTempPath );
printf( "Temp Directory: %s\n", szTempPath );
//获取当前的目录
CHAR szCurrent[MAX_PATH] = { 0 };
GetCurrentDirectory( MAX_PATH, szCurrent );
printf( "Current Directory: %s\n", szCurrent );
//设置当前的目录
SetCurrentDirectory( "C:\\" );
GetCurrentDirectory( MAX_PATH, szCurrent );
printf( "Current Directory: %s\n", szCurrent );
}
void UseDirectory( )
{
//创建目录
CreateDirectory( "C:\\testd", NULL );
//修改目录
MoveFile( "C:\\testd", "C:\\teste" );
//删除目录
RemoveDirectory( "C:\\testd" );
}
==========================================day13============================================================================================
一 Windows内存管理
1 地址空间
指针可以查找最大地址范围,例如32位操作系统
最大寻址范围为2^32。寻址空间越大,程序的编
写相对会容易。
2 Windows进程地址空间
2.1 用户空间 ( 例如:0 - 2G )
用户空间的代码,不能访问内核空间的地址。
用于存放用户的程序、代码、数据等。
2.1.1 空指针区( NULL区, 0-0xFFFF )
2.1.2 可以使用的( 0x10000 - 0x7FFEFFFF )
2.1.3 64K禁入区( 0x7FFF0000 - 0x7FFFFFFF )
2.2 内核空间 ( 例如:2G - 4G )
存放的是驱动、内存管理等等,它可以访问
用户空间的数据。
二 地址映射
1 区域
区域是一块连续的地址空间。目前区域的大小
都是64K。
1.1 保留区域 - 空闲区域,未被使用
1.2 私有区域 - 预定的区域
1.3 映像区域 - 存放代码
1.4 映射区域 - 存放数据
2 物理内存
可以使用内存。
3 虚拟内存
使用硬盘文件模拟内存。可以通过Windows进行
调整。
4 内存页
用于管理内存的最小单位,一般内存页大小为4K。
5 内存页的切换
5.1 根据地址,查找相应的内存页,是否在物理
内存上,如果找到,将地址转换为物理地址
返回数据;如果未找到,执行5.2。
5.2 在虚拟内存中查找相应的内存页。如果未找
到,返回错误;如果找到,执行5.3
5.3 在物理内存查找目前不使用的内存页,将内
存页放到虚拟内存。
5.4 将找到的内存页,放入已经释放的物理内存
上。
5.5 将地址转换为物理地址返回数据。
6 指针地址
31-------22 21---------12 11-------------0
页目(1024) 页表(1024) 页内偏移量(4096)
页目 - 页表
页表
...
页目
页目
...
7 内存使用
7.1 虚拟内存 - 分配大内存,一般是1M以上
7.2 堆内存 - 分配小而碎内存,一般是1M以下
7.3 栈内存 - 系统维护,一般是1M以下
二 虚拟内存
1 虚拟内存
适合大内存分配,分配效率高,可以只分配地址,
不立刻提交内存。
2 虚拟内存的信息
VOID GlobalMemoryStatus(
LPMEMORYSTATUS lpBuffer //内存信息
);
3 虚拟内存的使用
3.1 内存分配
LPVOID VirtualAlloc(
LPVOID lpAddress, //分配的地址
DWORD dwSize,
//分配的大小,一般为页的倍数
DWORD flAllocationType,
//分配方式
DWORD flProtect //权限
); 返回分配好的内存地址
MEM_COMMIT - 立刻提交
MEM_RESERVE - 保留方式
3.2 内存使用
对于采用MEM_RESERVE方式分配内存,需要
再次调用VirtualAlloc提交内存才能使用。
3.3 内存的释放
BOOL VirtualFree(
LPVOID lpAddress, //释放的地址
DWORD dwSize, //释放的大小
DWORD dwFreeType //释放的方式
);
MEM_DECOMMIT - 只释放内存
MEM_RELEASE - 释放内存和地址
三 堆内存
1 堆内存
小内存使用,1M之下。程序启动之后,至少
有一个堆,默认1M,堆大小不够可以默认扩展。
2 堆信息
当前进程的默认堆
HANDLE GetProcessHeap(VOID)
当前进程的所有堆
DWORD GetProcessHeaps(
DWORD NumberOfHeaps, //BUFF长度
PHANDLE ProcessHeaps //句柄的BUFF
); 返回HANDLE的数量
3 堆的使用
3.1 堆的创建
HANDLE HeapCreate(
DWORD flOptions, //创建方式
DWORD dwInitialSize, //初始化大小
DWORD dwMaximumSize //最大值
); 返回堆的句柄
3.2 内存分配
LPVOID HeapAlloc(
HANDLE hHeap, //堆句柄
DWORD dwFlags, //创建方式
DWORD dwBytes //分配的字节数
); 返回分配内存的地址
3.3 内存使用
3.4 内存释放
BOOL HeapFree(
HANDLE hHeap, //堆句柄
DWORD dwFlags, //释放方式
LPVOID lpMem //释放的地址
);
3.5 堆的销毁
BOOL HeapDestroy(
HANDLE hHeap //堆句柄
);
堆销毁后,堆内的内存全部释放。
4 malloc/HeapAlloc/VirtualAlloc
Windows下的关系
HeapAlloc内部调用了VirtualAlloc,效率比
VirtualAlloc低。
malloc内部调用了HeapAlloc,效率比
HeapAlloc 低。
malloc的内存分配
32 头 + 需要分配的大小 + 4 结束标识
四 栈内存
每个线程都会有默认的栈,默认大小为1M。
Windows下提供 _alloca,可以在栈上分配内存。
五 内存映射文件
1 内存映射文件
将文件映射为内存,可以像使用内存一样使用
文件。
2 内存映射文件的使用
2.1 打开或创建文件
CreateFile
2.2 创建内存映射文件
HANDLE CreateFileMapping(
HANDLE hFile, //文件句柄
LPSECURITY_ATTRIBUTES lpFileMappingAttributes,
//安全属性
DWORD flProtect, //保护方式
DWORD dwMaximumSizeHigh,//高4字
DWORD dwMaximumSizeLow, //低4字
LPCTSTR lpName //名字,可以为NULL
); 返回创建好的句柄
2.3 提交内存
LPVOID MapViewOfFile(
HANDLE hFileMappingObject,
//内存映射文件句柄
DWORD dwDesiredAccess,
//访问方式
DWORD dwFileOffsetHigh,
//高4字
DWORD dwFileOffsetLow,
//低4字
DWORD dwNumberOfBytesToMap
//提交的字节数
); 返回提交好地址的指针
2.4 使用内存
2.5 卸载内存
BOOL UnmapViewOfFile(
LPCVOID lpBaseAddress //地址
);
2.6 关闭内存映射文件
CloseHandle
2.7 关闭文件
CloseHandle
void MemInfo( )
{ //获取内存状态
MEMORYSTATUS status = { 0 };
status.dwLength = sizeof( status );
GlobalMemoryStatus( &status );
//
printf( "TotalPhys: %u\n", status.dwTotalPhys );
printf( "AvailPhys: %u\n", status.dwAvailPhys );
printf( "MemoryLoad: %u\n", status.dwMemoryLoad );
printf( "TotalPageFile: %u\n", status.dwTotalPageFile );
printf( "AvailPageFile: %u\n", status.dwAvailPageFile );
printf( "TotalVirtual: %u\n", status.dwTotalVirtual );
printf( "AvailVirtual: %u\n", status.dwAvailVirtual );
}
void GetInfo( )
{
//获取系统信息
SYSTEM_INFO info = { 0 };
GetSystemInfo( &info );
//内存页
printf( "Page Size: %d\n", info.dwPageSize );
//最小地址
printf( "Min Address: %08X\n",
info.lpMinimumApplicationAddress );
//最大地址
printf( "Max Address: %08X\n",
info.lpMaximumApplicationAddress );
//区域粒度
printf( "AllocationGranularity: %08X\n",
info.dwAllocationGranularity );
}
void MemInfo( )
{ //获取内存状态
MEMORYSTATUS status = { 0 };
status.dwLength = sizeof( status );
GlobalMemoryStatus( &status );
//
printf( "-------------------------------------\n");
printf( "TotalPhys: %u\n", status.dwTotalPhys );
printf( "AvailPhys: %u\n", status.dwAvailPhys );
printf( "MemoryLoad: %u\n", status.dwMemoryLoad );
printf( "TotalPageFile: %u\n", status.dwTotalPageFile );
printf( "AvailPageFile: %u\n", status.dwAvailPageFile );
printf( "TotalVirtual: %u\n", status.dwTotalVirtual );
printf( "AvailVirtual: %u\n", status.dwAvailVirtual );
}
void Virtual( )
{ //分配内存
LPSTR pszData = (LPSTR)VirtualAlloc( NULL,
1024 * 1024 * 1024,
MEM_RESERVE, PAGE_READWRITE );
MemInfo( );
getch( );
//提交内存
pszData = (LPSTR)VirtualAlloc( pszData,
1024 * 1024 * 1024,
MEM_COMMIT, PAGE_READWRITE );
MemInfo( );
getch( );
//使用内存
strcpy( pszData, "Hello Virual Alloc\n" );
printf( "%s", pszData );
MemInfo( );
getch( );
//释放内存
VirtualFree( pszData, 0, MEM_RELEASE );
MemInfo( );
}
堆操作
void HeapInfo( )
{ //得到默认堆
HANDLE hHeap = GetProcessHeap( );
printf( "Process Heap: %p\n", hHeap );
//得到所有堆
HANDLE hHeaps[256] = { 0 };
DWORD nCount = GetProcessHeaps( 256, hHeaps );
for( DWORD nIndex=0; nIndex<nCount; nIndex++ )
{
printf( " %d: %p\n", nIndex+1,
hHeaps[nIndex] );
}
}
void Heap( )
{ //创建堆
HANDLE hHeap = HeapCreate( 0,
1024 * 1024, 0 );
HeapInfo( );
//分配内存
LPSTR pszText = ( LPSTR )
HeapAlloc( hHeap, HEAP_ZERO_MEMORY, 100 );
//使用
strcpy( pszText, "Hello Heap" );
printf( "%s\n", pszText );
//释放内存
HeapFree( hHeap, 0, pszText );
//销毁堆
HeapDestroy( hHeap );
HeapInfo( );
}
- 学Windows时候的一篇笔记
- 学Unix时候的一篇笔记..
- 学PHP啦~我的第一篇笔记 helloworld
- 自己刚学html的时候记得笔记,别嫌丑,我就是这么学过来的
- 转一篇有用的博文《当你学不进去的时候,不妨看看大脑是怎么想的》
- 赶着学的第一篇
- 学php的时候wampserver的问题
- 学HTML时候同学们做的!
- 学C++不得不看的一篇文章
- 学C++不得不看的一篇文章
- 学C++不得不看的一篇文章
- 学C++不得不看的一篇文章
- 学C++不得不看的一篇文章
- 学C++不得不看的一篇文章
- 学C++不得不看的一篇文章
- 学C++不得不看的一篇文章
- [windows phone自学笔记] 第一篇 HelloWorld!
- [学]USB学习笔记 第一篇 初步了解USB系统
- hdu 2072 单词数
- 用非负矩阵分解来进行特征聚类
- C++语言特性(2)---构造函数与析构函数
- Linux的链接
- 9月24号,百度笔试
- 学Windows时候的一篇笔记
- Eclipse 3.7 SVN1.6.x 插件links方式安装
- java 集合类图
- vi 中输入中文问题
- .Net C#语法 构造函数与静态构造函数
- 疯狂java讲义 第二章 理解面向对象
- 在S5PV210开发板上搭建android2.3系统----基于x210开发板
- 线性表--数据结构
- linux 学习心得2011-9-24