windows程序设计(第5版 珍藏版)学习笔记

第1章 起步

windows简单程序示例及说明

#include <windows.h>//包含其他windows头文件

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
					PSTR szCmdLine, int iCmdShow)
					//hInstance实例句柄,数值,标识此程序,多路运行生成多个实例
					//hPrevInstance查看此参数可以知道是否有其他实例运行,win32中此参数弃用,总为0
					//szCmdLine运行命令行,启动时把文件装入内存
					//iCmdShow窗口如何显示(如最大化等)
{
   
     MessageBox (NULL, TEXT ("Hello, Windows 98!"), TEXT ("HelloMsg"), 2) ;
	 //参数1窗口句柄
	 //参数2显示文本
	 //参数3标题栏
	 //参数4设置窗口按钮,可组合文字+外观(page16)。eg:0-OK,1-OKorCANCLE
	 //另:TEXT ("Hello, Windows 98!")打包到宏代码里,为方便转换成Unicode

     return 0 ;
}

编译过程就是标准的C++程序编译过程
编译器将C源代码生成一个.OBJ目标文件
链接器将OBJ文件与lib库放到一起生成exe

??查看库程序文件列表

第2章 Unicode字符集

宽字符wchar_t定义如下:
typedef unsigned short wchar_t;
所以wchar_t为16位,可表示更多字符(char位8位)

wchar_t a[] = L"hello!";//L向编译器表明是宽字符
int i = sizeof(a);//i == 14
wchar_t b = 'h';//单个字符不需要加L
int d = wcslen(a);//d == 6,wcslen()代替原来的函数strlen();

#include <TCHAR.H>
该头文件目的是以一系列的宏来同时兼容宽字符和普通字符
例如名字为“_UNICODE”的标识符被定义了,
就有#define _tcslen wcslen #define wchar_t TCHAR
否则#define _tcslen strlen #define char TCHAR

#include <windows.h>
typedef CHAR *PCHAR,*LPCH ,*PCH,*NPSTR,*LPSTR ,*PSTR;
//PCHAR指向字符的char型指针
//PSTR,表示指向字符串的指针
typedef CONST CHAR *LPCCH, *PCCH,*LPCSTR ,*PCSTR;

知识点学习:#include <stdarg.h>可变参数列表
访问未命名的参数,首先必须在可变参数函数中声明va_list类型的变量。调用va_start并传入两个参数:第一个参数为va_list类型的变量,第二个为省略号前最后一个有名字的参数的名称,接着每一调用va_arg就会返回下一个参数,va_arg的第一个参数为va_list,第二个参数为返回的类型。最后va_end必须在函数返回前被va_list调用(va_list当作参数)(没有要求要读取完所有参数)。

#include <stdio.h>
#include <stdarg.h>
void printargs(int arg1, ...) /* 输出所有int类型的参数,直到-1结束 */
{
   
va_list ap;
int i;
va_start(ap, arg1);
for (i = arg1; i != -1; i = va_arg(ap, int))
printf("%d ", i);
va_end(ap);
putchar('\n');
}
int main(void)
{
   
printargs(5, 2, 14, 84, 97, 15, 24, 48, -1);
printargs(84, 51, -1);
printargs(-1);
printargs(1, -1);
return 0;
}
//result:
//5 2 14 84 97 15 24 48
//84 51
//1

格式化的消息框

#include <windows.h>
#include <tchar.h>     
#include <stdio.h>     

int CDECL MessageBoxPrintf (TCHAR * szCaption, TCHAR * szFormat, ...)
{
   
     TCHAR   szBuffer [1024] ; //缓冲区大小
     va_list pArgList ;
     va_start (pArgList, szFormat) ;

     _vsntprintf (szBuffer, sizeof (szBuffer) / sizeof (TCHAR), 
                  szFormat, pArgList) ;
	 //参数1,存储文字到szBuffer
	 //参数2,要写入的最大字符数,非字节数,所以要做除法
	 //参数3,格式化文字
	 //参数4.格式化文字中的一系列替换文字
     va_end (pArgList) ;

     return MessageBox (NULL, szBuffer, szCaption, 0) ;
}

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow) 
{
   
     int cxScreen, cyScreen ;

     cxScreen = GetSystemMetrics (SM_CXSCREEN) ;
     cyScreen = GetSystemMetrics (SM_CYSCREEN) ;
	 //得到显示器的像素宽度和高度
     MessageBoxPrintf (TEXT ("ScrnSize"), 
                       TEXT ("The screen is %i pixels wide by %i pixels high."),
                       cxScreen, cyScreen) ;
     return 0 ;
}

第3章 窗口与消息

//一个窗口类使用一个窗口过程(我理解就是响应函数)
//一个窗口类可以产生多个窗口
#include <windows.h>
//typedef unsigned int UINT;
//typedef char CHAR;
//typedef __nullterminated CHAR *NPSTR, *LPSTR, *PSTR;  __nullterminated表示一个以’\0’结尾的字符串
//so,PSTR表示非宽字符串的指针char*
//typedef _W64 unsigned int WPARAM
//typedef _W64 long LPARAM
//typedef _W64 long LRESULT
//page45匈牙利记法
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;//函数声明,消息处理函数
//#define WINAPI __stdcall 被这个关键字修饰的函数,其参数都是从右向左通过堆栈传递
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,//HINSTANCE实例
                    PSTR szCmdLine, int iCmdShow)
{
   
     static TCHAR szAppName[] = TEXT ("HelloWin") ;
     HWND         hwnd ;//窗口句柄
     MSG          msg ;//消息结构
     WNDCLASS     wndclass ;//窗口信息结构体
	//设置窗口的各个属性和参数,CS_等标识符均为数值常量(page43)
     wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
     wndclass.lpfnWndProc   = WndProc ;//对窗口过程函数的引用
     wndclass.cbClsExtra    = 0 ;//预留的额外空间??干什么用
     wndclass.cbWndExtra    = 0 ;
     wndclass.hInstance     = hInstance ;
	 //LoadXXX加载XXX函数
     wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;//默认图标NULL,自定义hInstance
     wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;//鼠标图标
     wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;//GetStockObject()获取一个图形对象,本例子中是画刷
     wndclass.lpszMenuName  = NULL ;//窗口类菜单,NULL表示无菜单
     wndclass.lpszClassName = szAppName ;//窗口类名称(当程序只创建一个窗口时,窗口类名称通常与程序名相同)

     if (!RegisterClass (&wndclass))//注册窗口
     {
   
          MessageBox (NULL, TEXT ("This program requires Windows NT!"), 
                      szAppName, MB_ICONERROR) ;
          return 0 ;
     }
     //创建窗口,返回值为指向窗口的句柄
	 //CreateWindowA和CreateWindowW处理ASCⅡ和Unicode
     hwnd = CreateWindow (szAppName,                  // 窗口类名称     //与窗口类建立关联
                          TEXT ("The Hello Program"), // title
                          WS_OVERLAPPEDWINDOW,        // 窗口格式(按位与的组合)
                          CW_USEDEFAULT,              // 初始X坐标
                          CW_USEDEFAULT,              // 初始Y坐标
                          CW_USEDEFAULT,              // 初始X方向尺寸
                          CW_USEDEFAULT,              // 初始Y方向尺寸
                          NULL,                       // 父窗口句柄      //顶级窗口
                          NULL,                       // 窗口菜单句柄
                          hInstance,                  // 程序实例句柄
                          NULL) ;                     // 创建参数
     
     ShowWindow (hwnd, iCmdShow) ;//显示窗口
     UpdateWindow (hwnd) ;//更新窗口的客户区
	 //GetMessage是从调用线程的消息队列里取得一个消息并将其放于指定的结构。
	 //此函数可取得与指定窗口联系的消息和由PostThreadMessage寄送的线程消息。
	 //此函数接收一定范围的消息值。GetMessage不接收属于其他线程或应用程序的消息。
	 //获取消息成功后,线程将从消息队列中删除该消息。
	 //函数会一直等待直到有消息到来才有返回值。
	 
	 //参数1:指向MSG结构的指针,该结构从线程的消息队列里接收消息信息。
	 //参数2:取得其消息的窗口的句柄。当其值取NULL时,GetMessage为任何属于调用线程的窗口检索消息,线程消息通过PostThreadMessage寄送给调用线程。
	 //参数3UNIT:指定被检索的最小消息值的整数。
	 //参数4UNIT:指定被检索的最大消息值的整数。
     while (GetMessage (&msg, NULL, 0, 0))
     {
   
          TranslateMessage (&msg) ;//TranslateMessage函数用于将虚拟键消息转换为字符消息。
          DispatchMessage (&msg) ;
     }
     return msg.wParam ;//从winmain中退出
}
//消息处理函数
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)//wParam与lParam传递提供关于消息的一些附加消息
{
   
     HDC         hdc ;//设备环境句柄
     PAINTSTRUCT ps ;//绘制结构
     RECT        rect ;//矩形结构
     
     switch (message)
     {
   
     case WM_CREATE:
          PlaySound (TEXT ("hellowin.wav"), NULL, SND_FILENAME | SND_ASYNC) ;//播放声音函数
          return 0 ;
          
     case WM_PAINT:
          hdc = BeginPaint (hwnd, &ps) ;//WM_PAINT消息必须以此函数开头,返回设备句柄
          //BeginPaint调用期间会擦除背景,用注册窗口类的时候的hbrBackground
          GetClientRect (hwnd, &rect) ;
          //使用环境句柄hdc只能在客户区绘制
          DrawText (hdc, TEXT ("Hello, Windows 98!"), -1, &rect,//绘制文本
                    DT_SINGLELINE | DT_CENTER | DT_VCENTER) ;
          
          EndPaint (hwnd, &ps) ;//WM_PAINT消息必须以此函数结尾,释放设备句柄
          return 0 ;
          
     case WM_DESTROY:
          PostQuitMessage (0) ;
          return 0 ;
     }
     return DefWindowProc (hwnd, message, wParam, lParam) ;//DefWindowProc此函数返回值必须从窗口过程中返回
}

其中GetMessage函数也可以使用PeekMessage,两者的区别是:链接

第20章 多任务和多线程

多线程1/10秒规则:一个消息队列线程处理一条消息的时候不应该花费1/10秒以上的时间。
但有些操作不适用,比如打开一个大的文件,把它加载到内存中。
多线程架构
主线程 - 创建所有窗口,包括窗口过程
其他线程 - 简单的后台运算,只和主线程通信
所有线程都是同一个进程的一部分,共享进程的所有资源,如内存及打开的文件,以及静态变量。
同步机制:semaphore信号量,critical section 临界区
i++;
16位程序中 被编译为两条机器代码指令,所以需要把代码放到临界区。
32位程序中 没有影响
WindowsNT 有一个函数能够让一个线程终止同一个进程中的另一个线程
创建一个执行线程的API函数

hThread = CreatThread(&security_attribute, dwStackSize, ThreadProc, pParam, dwFlags, &idThread);
//参数1:指向SECURITY_ATTRIBUTE结构的指针。 win98中没用,winNT可以设置为NULL
//参数2: 线程初始大小,0为默认值,可动态调整
//参数3:函数指针指向自己的线程函数 DWORD WINAPI ThreadProc(PVOID pParam);
//参数4:传递给线程函数的参数
//参数5:默认0,如果设置为CREATE_SUSPENDED表示线程创建后挂起,直到调用ResumeThread函数
//参数6:指针,指向新接收线程的ID值变量

也可以使用C的运行时函数库:

#include <PROCESS.H>
hThread = _beginthread(ThreadProc, uiStackSize, pParam);
//线程函数格式如下
void __cdecl ThreadProc (void *pParam);

环境设置:
项目设置 - c/c++ - category - code generation - use runtime library 改成多线程模式/MT
编程竞赛问题,非多线程实现代码(Page933)
学习注释如下:

/*---------------------------------------
   MULTI1.C -- Multitasking Demo
               (c) Charles Petzold, 1998
  ---------------------------------------*/

#include <windows.h>
#include <math.h>

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;

int cyChar ;//系统字体的高度

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow)
{
   
     static TCHAR szAppName[] = TEXT ("Multi1") ;
     HWND         hwnd ;
     MSG          msg ;
     WNDCLASS     wndclass ;
     
     wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
     wndclass.lpfnWndProc   = WndProc ;
     wndclass.cbClsExtra    = 0 ;
     wndclass.cbWndExtra    = 0 ;
     wndclass.hInstance     = hInstance ;
     wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
     wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
     wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
     wndclass.lpszMenuName  = NULL ;
     wndclass.lpszClassName = szAppName ;
     
     if (!RegisterClass (&wndclass))
     {
   
          MessageBox (NULL, TEXT ("This program requires Windows NT!"),
                      szAppName, MB_ICONERROR) ;
          return 0 ;
     }
     
     hwnd = CreateWindow (szAppName, TEXT ("Multitasking Demo"),//入口主函数调用WndProc,WndProc调用1234子窗口过程
                          WS_OVERLAPPEDWINDOW,
                          CW_USEDEFAULT, CW_USEDEFAULT,
                          CW_USEDEFAULT, CW_USEDEFAULT,
                          NULL, NULL, hInstance, NULL) ;
     
     ShowWindow (hwnd, iCmdShow) ;
     UpdateWindow 
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值