Win32API学习笔记第七章(二)

其实对话框不止这些(子窗口控件)
在书上我们可以看见,About3这个程序,实际上是自绘了一个确认图标。
首先我们自己给这个图标定义了一个类(说白了,这个图标实际上就是一个窗口,只是这里的窗口类被封装到了一个叫CustomControl的子窗口控制里面,这个控件会把Class这一栏空出来由用户自己选,然后实际上在创建了Dialog的时候就会调用CreateWindow来将这个用户自定的窗口创建出来。
再说下相互切换的Tab键相关的两个API:
GetNextDlgTabItem和GetNextGroupItem这里就可以得到前一个或后一个Tab键停留的组项(然后设置焦点就可以)同时,如果是自己的窗口的话,要加上WS_TABSTOP和WS_GROUP两个窗口风格才可以达到这个目的。
然后是非模态对话框:

1:

第一个是主窗口调用一个非模态对话框(这样子的对话框更像普通的子窗口一点)
此时我们需要自己为这个对话框写一个窗口过程,然后是创建窗口时:
CreateDialog(HINSTANCE,PTCHAR,父窗口窗口句柄 ,自己的窗口过程);
在窗口过程内我们就可以自定义各种各样的消息,并且可以在主窗口和这个对话框之间相互切换,而且很多的一些相关功能都有着对话框的性质,非常的方便
但是我们会发现一个问题:我们的消息循环只有一个,那要怎么办?
此时我们就要用到isDialogMessage这个函数来判断这个消息是否是属于后一个对话框的:

if(hWnd == 0||!isDialogMessage(hWnd,&msg))
{
    //默认的之前的窗口消息
}

这个函数有两个作用,第一:如果这个消息时属于这个对话框的消息,那么它将返回一个非零值,并且将这个消息发送到相应的窗口过程去,其次:如果这个消息不属于这个对话框,那么就返回一个0。
之前加了一个判断hWnd是否为0是因为,如果为0他将继续用无效的窗口句柄进行调用这个函数,所以这里时加以验证的一个机制,并且,这个hWnd被置为全局,以便执行:

case WM_CLOSE:
    DestoryWindow(hWnd);
    hWnd = 0;
    return 0;

这里非模态和模态的区别之一就是这里并不是调用EndDialog。

2:

我们还可以直接就将这个对话框置为主窗口,这就会大大简化了代码:

WNDCLASS wcex;
    wcex.style = CS_HREDRAW | CS_VREDRAW | WS_VISIBLE;
    wcex.lpfnWndProc    = WndProc;
    wcex.cbClsExtra     = 0;
    wcex.cbWndExtra     = DLGWINDOWEXTRA;    // 这里必须为DLGWINDOWEXTRA
    wcex.hInstance      = hInstance;
...
    wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName   = NULL;
    wcex.lpszClassName  = szWindowClass;

//然后是注册,之后就用
CreateDialog(HINSTANCE,PTCHAR,0,0);//后面两个为NULL就可以了

此时说实话这个就是一个窗口的创建(其尺寸,文字尺寸,标题都在资源文件里面声明了)两者时等价关系。
来看一个书上非常典型的例子:

/*----------------------------------------
   HEXCALC.C -- Hexadecimal Calculator
                (c) Charles Petzold, 1998
  ----------------------------------------*/

#include 

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

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow)
{
     static TCHAR szAppName[] = TEXT ("HexCalc") ;
     HWND         hwnd ;
     MSG          msg ;
     WNDCLASS     wndclass ;

     wndclass.style         = CS_HREDRAW | CS_VREDRAW;
     wndclass.lpfnWndProc   = WndProc ;
     wndclass.cbClsExtra    = 0 ;
     wndclass.cbWndExtra    = DLGWINDOWEXTRA ;    // Note!
     wndclass.hInstance     = hInstance ;
     wndclass.hIcon         = LoadIcon (hInstance, szAppName) ;
     wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
     wndclass.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1) ;
     wndclass.lpszMenuName  = NULL ;
     wndclass.lpszClassName = szAppName ;

     if (!RegisterClass (&wndclass))
     {
          MessageBox (NULL, TEXT ("This program requires Windows NT!"),
                      szAppName, MB_ICONERROR) ;
          return 0 ;
     }

     hwnd = CreateDialog (hInstance, szAppName, 0, NULL) ;

     ShowWindow (hwnd, iCmdShow) ;

     while (GetMessage (&msg, NULL, 0, 0))
     {
          TranslateMessage (&msg) ;
          DispatchMessage (&msg) ;
     }
     return msg.wParam ;
}

void ShowNumber (HWND hwnd, UINT iNumber)
{
     TCHAR szBuffer[20] ;

     wsprintf (szBuffer, TEXT ("%X"), iNumber) ;
     SetDlgItemText (hwnd, VK_ESCAPE, szBuffer) ;
}

DWORD CalcIt (UINT iFirstNum, int iOperation, UINT iNum)
{
     switch (iOperation)
     {
     case '=': return iNum ;
     case '+': return iFirstNum +  iNum ;
     case '-': return iFirstNum -  iNum ;
     case '*': return iFirstNum *  iNum ;
     case '&': return iFirstNum &  iNum ;
     case '|': return iFirstNum |  iNum ;
     case '^': return iFirstNum ^  iNum ;
     case '<': return iFirstNum << iNum ;
     case '>': return iFirstNum >> iNum ;
     case '/': return iNum ? iFirstNum / iNum: MAXDWORD ;
     case '%': return iNum ? iFirstNum % iNum: MAXDWORD ;
     default : return 0 ;
     }
}

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
     static BOOL  bNewNumber = TRUE ;
     static int   iOperation = '=' ;
     static UINT  iNumber, iFirstNum ;
     HWND         hButton ;

     switch (message)
     {
     case WM_KEYDOWN:                   // left arrow --> backspace
          if (wParam != VK_LEFT)
               break ;
          wParam = VK_BACK ;
                                        // fall through
     case WM_CHAR:
          if ((wParam = (WPARAM) CharUpper ((TCHAR *) wParam)) == VK_RETURN)
               wParam = '=' ;

          if (hButton = GetDlgItem (hwnd, wParam))
          {
               SendMessage (hButton, BM_SETSTATE, 1, 0) ;
               Sleep (100) ;
               SendMessage (hButton, BM_SETSTATE, 0, 0) ;
          }
          else
          {
               MessageBeep (0) ;
               break ;
          }
                                        // fall through
     case WM_COMMAND:
          SetFocus (hwnd) ;

          if (LOWORD (wParam) == VK_BACK)         // backspace
               ShowNumber (hwnd, iNumber /= 16) ;

          else if (LOWORD (wParam) == VK_ESCAPE)  // escape
               ShowNumber (hwnd, iNumber = 0) ;

          else if (isxdigit (LOWORD (wParam)))    // hex digit
          {
               if (bNewNumber)
               {
                    iFirstNum = iNumber ;
                    iNumber = 0 ;
               }
               bNewNumber = FALSE ;

               if (iNumber <= MAXDWORD >> 4)
                    ShowNumber (hwnd, iNumber = 16 * iNumber + wParam -
                    (isdigit (wParam) ? '0': 'A' - 10)) ;
               else
                    MessageBeep (0) ;
          }
          else                                    // operation
          {
               if (!bNewNumber)
                    ShowNumber (hwnd, iNumber =
                         CalcIt (iFirstNum, iOperation, iNumber)) ;
               bNewNumber = TRUE ;
               iOperation = LOWORD (wParam) ;
          }
          return 0 ;

     case WM_DESTROY:
          PostQuitMessage (0) ;
          return 0 ;
     }
     return DefWindowProc (hwnd, message, wParam, lParam) ;
}

非常巧妙的是:
这里将所有的非Char类键盘消息全部丢给了默认的窗口过程处理,那么只需要在控件支持的情况下,我们就可以做到Tab切换等一系列操作,并且借助于每个消息之间的关系,将撤回键(VK_BACK)一直下调到COMMAND,回车键转化等等。。。。
(这个程序我自己在VS2017上实现,无法显示窗口,目前不知道原因,找到了原因的话会即使更新的)

你可能感兴趣的:(windows程序设计)