windowAPI笔记(1)

类别:编程语言 点击:0 评论:0 推荐:

走了一趟MFC,虽然MFC封装了的类很好用,但是总是感觉到对MFC的了解只能停留在表面上,很难进一步地理解MFC.关键原因还是自己对windowsAPI学习的不够,现在打算丢掉MFC一段时间,先还是把windowAPI回顾一便,加深点印象.

特地在网上下了本大师侯捷的<<windows程序设计>>,打算结合这本书在学好window的基础的同时把多线程和dll.但是光看书是不够的,必须在看书的时候自己动手设计点东西出来.所以我打算设计一个小软件同时包含dll,多线程,等基本的技术.现在的基本设想是搞一个类QQ的通信软件,现在还只是一个设想,基本的框架和功能还没有设计,过几天来具体设计一下.用API难度比较大,不过慢慢来,一口吃不一个胖子,时间长点应该没关系.相信我能坚持把这个软件做完的.

////引用侯捷老师书上的开始一段,也是入们的一段

#include <windows.h>


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


int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
     
     PSTR szCmdLine, int iCmdShow)
     
{
 
    static TCHAR szAppName[] = TEXT ("HelloWin") ;
 
    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,      // window class name
       
  TEXT ("The Hello Program"),   // window caption
       
  WS_OVERLAPPEDWINDOW,  // window style
       
  CW_USEDEFAULT,// initial x position
       
  CW_USEDEFAULT,// initial y position
       
  CW_USEDEFAULT,// initial x size
       
  CW_USEDEFAULT,// initial y size
       
  NULL,                 // parent window handle
       
  NULL,            // window menu handle
       
  hInstance,   // program instance handle
       
  NULL) ;      // creation parameters
 
 
 
    ShowWindow (hwnd, iCmdShow) ;
 
    UpdateWindow (hwnd) ;
 
 
 
    while (GetMessage (&msg, NULL, 0, 0))
       
    {
       
  TranslateMessage (&msg) ;
       
  DispatchMessage (&msg) ;
       
    }
 
    return msg.wParam ;
 
}


LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)

{
 
    HDC                   hdc ;
 
    PAINTSTRUCT ps ;
 
    RECT          rect ;
 
 
 
    switch (message)
       
    {
       
    case WM_CREATE:
       
  PlaySound (TEXT ("hellowin.mp3"), NULL, SND_FILENAME | SND_ASYNC) ;
       
  return 0 ;
       
  
    case   WM_PAINT:
       
  hdc = BeginPaint (hwnd, &ps) ;
       
       
       
  GetClientRect (hwnd, &rect) ;
       
       
       
  DrawText (hdc, TEXT ("Hello, Windows 2000!"), -1, &rect,
   
   DT_SINGLELINE | DT_CENTER | DT_VCENTER) ;
       
  EndPaint (hwnd, &ps) ;
       
  return 0 ;
       
       
       
    case   WM_DESTROY:
       
  PostQuitMessage (0) ;
       
  return 0 ;
       
    }
 
 return DefWindowProc (hwnd, message, wParam, lParam) ;
 
}

///////////////////////////////////////--------------------------------------------------

对没个细节的说明

窗口的设计就不说了,以前对这个看得太熟悉了

对句柄的一点小误会澄清一下

以前老是弄不清楚

HWND和HINSTANCE

hinstance是进程本身的句柄,牛的windows核心编程上说就是进程的在内存中开始的地址而HWND是指向一个窗口的句柄

三个大写标识符,用于不同型态的「句柄」:

标识符

含义

HINSTANCE

执行实体(程序自身)句柄

HWND

窗口句柄

HDC

设备内容句柄

下面的是匈牙利表示法的一些列子

前缀

数据型态

c

char或WCHAR或TCHAR

by

BYTE (无正负号字符)

n

short

i

int

x, y

int分别用作x坐标和y坐标

cx, cy

int分别用作x长度和y长度;C代表「计数器」

b或f

BOOL (int);f代表「旗标」

w

WORD (无正负号短整数)

l

LONG (长整数)

dw

DWORD (无正负号长整数)

fn

function(函数)

s

string(字符串)

sz

以字节值0结尾的字符串

h

句柄

p

指标

在窗口创建之前要调用RegisterClass

以前对RegisterClass也不是很了解,只是知道有这一步

MSDN:

The RegisterClass function registers a window class for subsequent use in calls to the CreateWindow or CreateWindowEx function.(RegisterClass函数来Register一个窗口类为后面的CreateWindow or CreateWindowEx 函数来调用)

大致意思是如果不Register那么CreateWindow or CreateWindowEx 函数就无法创建你想要的窗口

以前对CreateWindow or CreateWindowEx 也很熟悉了,这里就不在累赘了.

ShowWindow在MSDN的"注意"上上是这样说明的

To perform certain special effects when showing or hiding a window, use AnimateWindow.

The first time an application calls ShowWindow, it should use the WinMain function's nCmdShow parameter as its nCmdShow parameter. Subsequent calls to ShowWindow must use one of the values in the given list, instead of the one specified by the WinMain function's nCmdShow parameter.

As noted in the discussion of the nCmdShow parameter, the nCmdShow value is ignored in the first call to ShowWindow if the program that launched the application specifies startup information in the structure. In this case, ShowWindow uses the information specified in the STARTUPINFO structure to show the window. On subsequent calls, the application must call ShowWindow with nCmdShow set to SW_SHOWDEFAULT to use the startup information provided by the program that launched the application. This behavior is designed for the following situations:

Applications create their main window by calling CreateWindow with the WS_VISIBLE flag set. Applications create their main window by calling CreateWindow with the WS_VISIBLE flag cleared, and later call ShowWindow with the SW_SHOW flag set to make it visible.

The RegisterClass function registers a window class for subsequent use in calls to the CreateWindow or CreateWindowEx function.(RegisterClass函数来Register一个窗口类为后面的CreateWindow or CreateWindowEx 函数来调用)

大致意思是如果不Register那么CreateWindow or CreateWindowEx 函数就无法创建你想要的窗口

以前对CreateWindow or CreateWindowEx 也很熟悉了,这里就不在累赘了.

ShowWindow在MSDN的"注意"上上是这样说明的

To perform certain special effects when showing or hiding a window, use AnimateWindow.

The first time an application calls ShowWindow, it should use the WinMain function's nCmdShow parameter as its nCmdShow parameter. Subsequent calls to ShowWindow must use one of the values in the given list, instead of the one specified by the WinMain function's nCmdShow parameter.

As noted in the discussion of the nCmdShow parameter, the nCmdShow value is ignored in the first call to ShowWindow if the program that launched the application specifies startup information in the structure. In this case, ShowWindow uses the information specified in the STARTUPINFO structure to show the window. On subsequent calls, the application must call ShowWindow with nCmdShow set to SW_SHOWDEFAULT to use the startup information provided by the program that launched the application. This behavior is designed for the following situations:

Applications create their main window by calling CreateWindow with the WS_VISIBLE flag set. Applications create their main window by calling CreateWindow with the WS_VISIBLE flag cleared, and later call ShowWindow with the SW_SHOW flag set to make it visible.

这里重点要提的是UpdateWindow:

The UpdateWindow function updates the client area of the specified window by sending a WM_PAINT message to the window if the window's update region is not empty. The function sends a WM_PAINT message directly to the window procedure of the specified window, bypassing the application queue. If the update region is empty, no message is sent.

当窗口收到WM_PAINT 消息的时候,如果窗口的更新区不是空的窗口被更新,WM_PAINT 消息被至于指定进程的窗口,放入该进程的消息队列.如果更新区是空的,那么将没有消息被发送,即WM_PAINT 不会被至于消息队列.1)WM_PAINT:

以前对这个WM_PAINT 的概念很模糊,现在感觉有个比较清醒的认识了

MSDN上是这样申明的

The WM_PAINT message is sent when the system or another application makes a request to paint a portion of an application's window. The message is sent when the UpdateWindow or RedrawWindow function is called, or by the DispatchMessage function when the application obtains a WM_PAINT message by using the GetMessage or PeekMessage function.

当系统或者应用程序发出一个重绘一个应用程序的一个窗口的时候WM_PAINT的消息被送出,即当UpdateWindow or RedrawWindow 函数被调用时,WM_PAINT

然后被GetMessage or PeekMessage 捕获.然后被DispatchMessage 处理,送入消息队列.

调用UpdateWindow之后,窗口就出现在视讯显示器上。程序现在必须准备读入使用者用键盘和鼠标输入的数据。Windows为当前执行的每个Windows程序维护一个「消息队列」。在发生输入事件之后,Windows将事件转换为一个「消息」并将消息放入程序的消息队列中。

while       (GetMessage (&msg, NULL, 0, 0))
       
{
    TranslateMessage (&msg) ;
       
    DispatchMessage (&msg) ;
}
注意这里的GetMessage (&msg, NULL, 0, 0)是从消息队列中取出一个消息

以前我错误地认为它是来接受消息的

那么消息是怎么样被放入消息队列的呢?

还是引用上面的一句话:The WM_PAINT message is sent when the system or another application makes a request to paint a portion of an application's window

//当系统或者应用程序发出一个重绘一个应用程序的一个窗口的时候WM_PAINT的消息被发出

接下来的问题又出现了,我们怎么知道什么时候应该重绘一个应用程序的窗口呢?

这个可以参看侯捷的<<windows程序设计>>的 输出文字 那章的第一节.

最后一点不太明白的就是退出函数

WM_DESTROY消息

程序通过PostQuitMessage以标准方式响应WM_DESTROY消息

该函数在程序的消息队列中插入一个WM_QUIT消息。前面提到过,GetMessage对于除了WM_QUIT之外的从消息队列中取出的所有消息都传回非0值。而当GetMessage得到一个WM_QUIT消息时,它传回0。这将导致WinMain退出消息循环

传回0以为着while (GetMessage (&msg, NULL, 0, 0))消息循环将被停止.

这段程序的函数调用:

HELLOWIN至少调用了18个Windows函数。下面以它们在HELLOWIN中出现的次序列出这些函数以及各自的简明描述:

LoadIcon 加载图标供程序使用。
  LoadCursor 加载鼠标光标供程序使用。
  GetStockObject 取得一个图形对象(在这个例子中,是取得绘制窗口背景的画刷对象)。
  RegisterClass 为程序窗口注册窗口类别。
  MessageBox 显示消息框。
  CreateWindow 根据窗口类别建立一个窗口。
  ShowWindow 在屏幕上显示窗口。
  UpdateWindow 指示窗口自我更新。
  GetMessage 从消息队列中取得消息。
  TranslateMessage 转译某些键盘消息。
  DispatchMessage 将消息发送给窗口消息处理程序。
  PlaySound 播放一个声音文件。
  BeginPaint 开始绘制窗口。
  GetClientRect 取得窗口显示区域的大小。
  DrawText 显示字符串。
  EndPaint 结束绘制窗口。
  PostQuitMessage 在消息队列中插入一个「退出程序」消息。
  DefWindowProc 执行内定的消息处理。

 

本文地址:http://com.8s8s.com/it/it22923.htm