学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开发环境

最常用的开发环境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 执行

   

三 编写第一个窗口程序

入口函数

注册窗口

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; 

定义窗口函数

  LRESULT CALLBACK WindowProc(

  HWND hwnd, //窗口句柄

  UINT uMsg, //消息ID

  WPARAM wParam, //消息附加参数

  LPARAM lParam  //消息附加参数

);

创建窗口   

  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 //创建附加参数

);

创建成功返回窗口句柄

显示窗口

ShowWindow - 显示或隐藏窗口

UpdateWindow - 更新窗口画面

消息循环

  GetMessage - 获取消息

  DispatchMessage - 派发消息

 

四 资源的使用

定义图标

  ICON

定义资源脚本

  定义资源的ID和路径、数据等信息

  文件类型:.rc

3 RC编译资源

  使用RC编译成 .res 文件

链接到程序

  使用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 ASCII

    使用7位表示1个字符,用0-127表示128个字符

  1.2 扩展ASCII

    使用8位表示1个字符,用0-255表示256个字符。

    代码页(Code page):通过代码页可以切换

      数字所代表的字符。

  1.3 多字节字符集 DBCS

    使用8位或者16位表示一个字符。

    例如:字符串 AB

           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输出

   printfUNICODE的输出支持不好,因此在

   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.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消息机制

消息机制概述

过程驱动 程序的执行过程是预先定义好的。

事件驱动 程序的执行过程是随机的,是由

  使用者来决定。

 

Windows消息机制是采用事件驱动的方式。

消息的使用

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.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

消息队列

Windows用先进先出的队列维护消息。

4.1 系统消息队列

由操作系统维护的消息队列。

4.2 应用程序消息队列(线程消息队列)

  各个线程都具有自己的消息队列。

消息和消息队列

根据消息和消息队列之间的使用关系,将消息

分成两大类。

5.1 队列消息

进入到消息队列中的消息。例如:鼠标、

键盘、WM_PAINTWM_TIMERWM_QUIT

使用 PostMessage 发送消息

5.2 非队列消息

不进入消息队列,直接发送给指定的窗口。

例如:WM_CREATE,WM_SIZE,WM_DESTROY

使用 SendMessage 发送消息。

消息的获取

GetMessagePeekMessage消息的获取

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 - 让出控制权,让程序继续执行。

消息的发送

PostMessage - 将消息放入线程消息队列,

立刻返回。消息不能确定是否被正确响应。

SendMessage - 直接将消息发送到指定窗口的

  窗口处理函数,并获取消息的执行结果。

二 WM_PAINT 消息

绘制窗口消息

当窗户中有无效绘图的区域,就会产生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==========================================================================================================

一 菜单和命令

菜单

菜单 使用一个 HMENU 句柄表示。

菜单项 每一个菜单项都具有一个ID号,可以

根据这个ID,执行不同的命令。

菜单的相关

CreateMenu - 创建菜单

DestroyMenu - 销毁菜单

AppendMenu - 追加菜单项

InsertMenu - 插入菜单项

DeleteMenu - 删除菜单项

...

菜单的使用

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.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之后产生。

二 资源的使用

资源

图标、鼠标、菜单、加速键、字符串、

对话框资源、图片、自定义资源等。

图标

图标的常用大小 16X16 32X32 48X48

LoadIcon 加载图标

HICON LoadIcon(

  HINSTANCE hInstance, //应用程序实例句柄

  LPCTSTR lpIconName   //ICONID名称

); 返回HICON句柄

 

  3 光标

  3.1 光标的使用

  光标常用大小 16X16 32X32

  热点 光标能够产生点击效果的点,1个像素

   大小

  LoadCursor 加载光标

3.2 WM_SETCURSOR

在消息内可以设置光标样式。

字符串

4.1 添加字符串资源

4.2 加载字符串资源

int LoadString(

  HINSTANCE hInstance,  //应用程序句柄

  UINT uID,             //字符串ID

  LPTSTR lpBuffer,      //存放字符串的BUFF

  int nBufferMax        //BUFF的大小

);

菜单

5.1 添加菜单资源

5.2 加载菜单资源

HMENU LoadMenu(

  HINSTANCE hInstance,  //应用程序句柄

  LPCTSTR lpMenuName //菜单的ID

); 返回菜单的句柄

加速键

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绘图

绘图设备

例如显示器、打印机等等,通过DC设备描述表

Device Context),Windows程序中使用HDC

表示DC的句柄。

颜色

显示器颜色是通过RedGreenBlue,每个

8位表示,用24位表示一个颜色。可以

表示的颜色数量为 224次方。

常用颜色数量

16位色 颜色数量为2^16, 

32位色 颜色数量为2^24, 8位表示灰度

         或者透明度

Window程序中使用 COLORREF 表示颜色数据

COLORREF nColor = RGB( 200, 200, 200 );         

获取一个颜色的RGB

GetRValueGetGValueGetBValue

点的绘制

COLORREF SetPixel(

  HDC hdc, //DC句柄

  int X, //DCX坐标 

  int Y, //DCY坐标 

  COLORREF crColor   //绘制的颜色

);

GetPixel 返回指定点的颜色

线的绘制

当前点 绘图的起始点。

4.1 直线

MoveToEx - 移动当前点到指定的位置

LineTo - 从当前点到指定位置绘制直线,

会改变当前点的位置到指定位置。

4.2 弧线

SetArcDirection - 设置切弧的方向

Arc - 绘制弧,不影响当前点

ArcTo - 影响当前点

AngelArc - 用角度绘制弧

4.3 折线

Polyline - 绘制折线

PolylineTo - 绘制折线并连接当前点

PolyPolyline - 绘制多组折线

4.4 Biezer曲线

PolyBezier - 绘制Biezer曲线

PolyBezierTo - 绘制Biezer曲线并连接当前点

封闭图形

5.1 矩形

Rectangle

RoundRect

5.2 椭圆

Ellipse

5.3 多边形

Polygon

5.4 扇形

Pie

5.5 弓形

Chord

二 绘图对象

绘图对象GDI Object

画笔、画刷、位图、字体

画笔的使用

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.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 屏幕坐标系 以屏幕的左上角为(0,0)

向右为X正方向,向下为Y正方向

1.1.2 窗口坐标系 以窗口的左上角为(0,0)

向右为X正方向,向下为Y正方向

1.1.3 客户区坐标系 以窗口客户区的左上角

  为(0,0)点,向右为X正方向,向下为Y正方向

1.2 逻辑坐标系

以逻辑单位,例如毫米、英寸为单位的坐标系。

几乎所有的绘图函数,都使用的是逻辑坐标系

1.3 设备坐标系和逻辑坐标系

绘图时,使用逻辑坐标系,API内部进行转换,

将逻辑坐标转换到设备坐标,在设备上显示

对应图形。

映射模式

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 //旧的坐标原点

);

二 文字和字体

文字绘制

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   //字符间距的数组

);

字符绘制属性

设置文字颜色

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   //背景绘制模式

); 返回原来的背景绘制模式

字体

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.2 无模式对话框 显示后,所在的应用程序

其他窗口可以获得输入焦点,接受输入。

对话框的使用方式

2.1 定义对话框资源

2.2 注册对话框窗口(可选)

2.3 创建和显示对话框

2.4 消息处理

2.5 对话框的结束

模式对话框

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.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.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已经定义好的窗口类型,例如静态框、

按钮、文本编辑框等。

控件的使用

使用CreateWindow/CreateWindowEx创建,处理

控件消息。

控件的消息

通过消息设置或获取控件状态和信息。

通过消息响应按钮的处理(通知消息 - WM_COMMAND)

二 静态框

静态框

静态框 窗口类的名称 STATIC,可以在窗口上

显示文字或图片。

从风格上分类:

显示文字 - SS_SIMPLE

显示图片 - SS_ICON/SS_BITMAP

静态框的使用

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和控件窗口句柄发送给发送给父窗口。

 

三 按钮

按钮的分类

按钮的窗口类名称 “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

下压式按钮

3.2.1 创建CreateWindow

3.2.2 消息处理

3.2.3 通知消息

BN_CLICKED - 当单击按钮,通知父窗口。

单选按钮

3.3.1 创建CreateWindow

BS_AUTORADIOBUTTON - 可以自动完成选择

BS_RADIOBUTTON - 需要手动完成选择

单选框的分组可以使用WS_GROUP风格。

在需要分组的第一个选项上,添加WS_GROUP风格。

3.3.2 消息处理

BM_SETCHECK

BM_GETCHECK

......

3.3.3 通知消息

BN_CLICKED - 当单击按钮,通知父窗口。

......

复选按钮

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.1 创建CreateWindow

使用BS_GROUPBOX风格

四 文本编辑框

文本编辑框分类

1.1 单行编辑框 默认单行

1.2 多行编辑框 - ES_MULTILINE

1.3 密码编辑框 - ES_PASSWORD

文本编辑框的使用

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 简单组合框 - CBS_SIMPLE

1.2 下拉式组合框 - CBS_DROPDOWN

1.3 下拉列表式组合框 - CBS_DROPDOWNLIST

组合框的使用

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.2 多列 - LBS_MULTICOLUMN

列表框的使用

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 水平滚动条 - SBS_HORZ

1.2 垂直滚动条 - SBS_VERT

滚动条的使用

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.1 C和静态库

2.1.1 创建库

2.1.2 实现库函数

添加扩展名为.C的文件和相应的函数。

2.1.3 使用库函数

库的导入:

1)使用项目的SettingLink的设置

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.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 )

使用DEF文件导出

项目中增加.def文件,将导出函数添加

DEF中。

  3)动态库的LIB文件不同与静态库。

3.2.3 库的使用 隐式链接

1)导入库

导入动态库的LIB文件。

2)定义函数原型

1 _declspec( dllimport )

对于使用extern C”导出,必须也添加

extern “C”

3)使用库函数

4DLL存放路径

程序搜索DLL时,查找路径

程序相同目录下

程序工作目录

3 Windows\System32

4 Windows\System

5 Windows 目录

环境变量 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 - 4K8K

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内存管理

地址空间

指针可以查找最大地址范围,例如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 

存放的是驱动、内存管理等等,它可以访问

用户空间的数据。

二 地址映射

区域

区域是一块连续的地址空间。目前区域的大小

都是64K

1.1 保留区域 空闲区域,未被使用

1.2 私有区域 预定的区域

1.3 映像区域 存放代码

1.4 映射区域 存放数据

物理内存

可以使用内存。

虚拟内存

使用硬盘文件模拟内存。可以通过Windows进行

调整。

内存页

用于管理内存的最小单位,一般内存页大小为4K

内存页的切换

5.1 根据地址,查找相应的内存页,是否在物理

内存上,如果找到,将地址转换为物理地址

返回数据;如果未找到,执行5.2

5.2 在虚拟内存中查找相应的内存页。如果未找

到,返回错误;如果找到,执行5.3

5.3 在物理内存查找目前不使用的内存页,将内

存页放到虚拟内存。

5.4 将找到的内存页,放入已经释放的物理内存

上。

5.5 将地址转换为物理地址返回数据。

指针地址

 31-------22 21---------12 11-------------0

   页目(1024)   页表(1024)   页内偏移量(4096)

       页目 页表

           页表

           ...

    页目

    页目

    ...

 7 内存使用

  7.1 虚拟内存 分配大内存,一般是1M以上

  7.2 堆内存 分配小而碎内存,一般是1M以下

  7.3 栈内存 系统维护,一般是1M以下

 

二 虚拟内存

虚拟内存

适合大内存分配,分配效率高,可以只分配地址,

不立刻提交内存。

虚拟内存的信息

VOID GlobalMemoryStatus(

  LPMEMORYSTATUS lpBuffer //内存信息

);

虚拟内存的使用

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 - 释放内存和地址

三 堆内存

堆内存

小内存使用,1M之下。程序启动之后,至少

有一个堆,默认1M,堆大小不够可以默认扩展。

堆信息

当前进程的默认堆

HANDLE GetProcessHeap(VOID) 

当前进程的所有堆

DWORD GetProcessHeaps(

  DWORD NumberOfHeaps, //BUFF长度

  PHANDLE ProcessHeaps //句柄的BUFF

); 返回HANDLE的数量

堆的使用

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,可以在栈上分配内存。

五 内存映射文件

内存映射文件

将文件映射为内存,可以像使用内存一样使用

文件。

内存映射文件的使用

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( );

}

   

 

 

 

  

原创粉丝点击