为什么模仿MFC的方式把窗体注册和创建过程放到WinMain外部就失败?#include <windows.h>
INT  cxChar=0, cxCaps=0, cyChar=0, cxClient=0, cyClient=0, iMaxWidth=0,  iVertPos=0, iHorzPos=0, iPaintBeg=0, iPaintEnd=0;
TCHAR pz[9][20];
TCHAR szAppName[] = TEXT ("Metrics") ;
PAINTSTRUCT ps ;//
SCROLLINFO  si ; //滚动条信息
HWND hwnd=NULL;//窗体句柄
HINSTANCE hInst=NULL;//存放hInstance
TEXTMETRIC  tm ;
BOOL InitApplication(HINSTANCE);//窗体注册函数
BOOL InitInstance(HINSTANCE,INT);//窗体创建显示函数
INT Create();//WM_CREATE消息处理函数
INT Paint();//WM_PAINT消息处理函数
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,PSTR szCmdLine, int iCmdShow)
{
MSG   msg ;
/*****************************************/
    if(!hInstance)
        if(!InitApplication(hInstance))//注册窗体
                return 0;
    if(!InitInstance(hInstance,iCmdShow))//创建并显示更新窗体
        return 0;
/****************************************/
        while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
BOOL InitApplication(HINSTANCE hInstance)
{//注册窗体
    WNDCLASS wndclass ;
wndclass.style      = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc=(WNDPROC) 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 ("Program requires Windows NT!"), szAppName, MB_ICONERROR) ;
return FALSE ;
}
    return TRUE;
}
BOOL InitInstance(HINSTANCE hInstance,INT iCmdShow )
{//创建并显示窗体
    hInst=hInstance;//保存hInstance
hwnd = CreateWindow (szAppName,
                     TEXT ("九九乘法表"),
                     WS_OVERLAPPEDWINDOW | WS_VSCROLL | WS_HSCROLL,CW_USEDEFAULT,
                     CW_USEDEFAULT,
                     CW_USEDEFAULT,
                     CW_USEDEFAULT,
                     NULL,
                     NULL,
                     hInstance,
                     NULL) ;
/**************************************************
每次都在这里返回失败信息,窗体的注册成功,但创建失败
***************************************************/
    if(!hwnd)
    {//每次执行都在这里返回失败信息,为什么总返回失败信息?
        MessageBox(NULL,TEXT("窗体创建失败!"),TEXT("ERROR"),MB_ICONERROR);
        return FALSE;
    }
ShowWindow (hwnd, iCmdShow) ;
UpdateWindow (hwnd) ;
    return TRUE;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc ;
switch (message)
{
case WM_CREATE:
            if(Create())return 0 ; //调用Create函数(将处理写在WndProc函数体外部)
            else
            {
                MessageBox(NULL,TEXT("ERROR"),TEXT("创建窗口失败!"),MB_ICONERROR);
                return 0;
            }
  case WM_SIZE:
cxClient = LOWORD (lParam) ;
cyClient = HIWORD (lParam) ; // Set vertical scroll bar range and page size垂直条
si.cbSize  = sizeof (si) ;
si.fMask   = SIF_RANGE | SIF_PAGE ;
si.nMin    = 0 ;
si.nMax    = 30 - 1 ;//垂直条的最大宽度,每单位代表一个字符宽度
si.nPage   = cyClient / cyChar ;
SetScrollInfo (hwnd, SB_VERT, &si, TRUE) ;
// Set horizontal scroll bar range and page size水平条
si.cbSize  = sizeof (si) ;
si.fMask   = SIF_RANGE | SIF_PAGE ;
si.nMin    = 0 ;
si.nMax    = 120; //2 + iMaxWidth / cxChar ;//设置水平条的最大宽度,每单位代表一行高度
si.nPage   = cxClient / cxChar ;
SetScrollInfo (hwnd, SB_HORZ, &si, TRUE) ;
return 0 ;
          
case WM_VSCROLL://垂直滚动条的移动设置
// Get all the vertical scroll bar information
si.cbSize  = sizeof (si) ;
si.fMask   = SIF_ALL ;
GetScrollInfo (hwnd, SB_VERT, &si) ;
// Save the position for comparison later on
iVertPos = si.nPos ;
switch (LOWORD (wParam))
{
case SB_TOP: //滚动条置顶
si.nPos  = si.nMin ;
break ;
               
case  SB_BOTTOM: //垂直条置底
        si.nPos  = si.nMax ;
    break ;
               
case SB_LINEUP://上移一行
si.nPos -= 1 ;
break ;
               
case  SB_LINEDOWN:
si.nPos += 1 ;
break ;
               
case  SB_PAGEUP: //上移一页
si.nPos -= si.nPage ;
break ; case  SB_PAGEDOWN:
si.nPos += si.nPage ;
break ;
               
case  SB_THUMBTRACK: //轨迹移动
si.nPos = si.nTrackPos ;
break ;
               
default:
break ;         
}
// Set the position and then retrieve it.  Due to adjustments
//  by Windows it may not be the same as the value set. si.fMask = SIF_POS ;
SetScrollInfo (hwnd, SB_VERT, &si, TRUE) ;
GetScrollInfo (hwnd, SB_VERT, &si) ; // If the position has changed, scroll the window and update it
if (si.nPos != iVertPos)
    {//垂直滚动条发生移动,窗口更新
ScrollWindow ( hwnd, 0, cyChar * (iVertPos - si.nPos), NULL, NULL) ;
UpdateWindow (hwnd) ;
}
return 0 ;
case WM_HSCROLL: //水平滚动条在移动设置
// Get all the vertical scroll bar information
si.cbSize = sizeof (si) ;
si.fMask  = SIF_ALL ; // Save the position for comparison later on
GetScrollInfo (hwnd, SB_HORZ, &si) ;
iHorzPos = si.nPos ;//滚动条位置 switch (LOWORD (wParam))
{
case  SB_LINELEFT: //左移一单位
si.nPos -= 1 ;
break ;
               
case  SB_LINERIGHT:
si.nPos += 1 ;
break ;
               
case  SB_PAGELEFT://左移一页
si.nPos -= si.nPage ;
break ;
               
case  SB_PAGERIGHT:
si.nPos += si.nPage ;
break ;
               
case  SB_THUMBPOSITION:  //轨迹移动
si.nPos = si.nTrackPos ;
break ;
               
default :
break ;
}
// Set the position and then retrieve it.  Due to adjustments
//   by Windows it may not be the same as the value set. si.fMask = SIF_POS ;
SetScrollInfo (hwnd, SB_HORZ, &si, TRUE) ; //设置滚动条信息
GetScrollInfo (hwnd, SB_HORZ, &si) ;//获取滚动条信息
          
// If the position has changed, scroll the window  if (si.nPos != iHorzPos)
{//水平滚动条移动
ScrollWindow ( hwnd, cxChar * (iHorzPos - si.nPos), 0, NULL, NULL) ;
        UpdateWindow(hwnd);
}
return 0 ;
case WM_PAINT :
            if(Paint())return 0 ;//调用Paint函数 ,处理过程在WndProc外部
            else MessageBox(NULL,TEXT("ERROR"),TEXT("Paint函数调用失败"),MB_ICONERROR);//失败
          
case WM_DESTROY :
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}

解决方案 »

  1.   

    INT Create()
    {//处理WM_CREATE消息
        HDC hdc = GetDC (hwnd) ;
        GetTextMetrics (hdc, &tm) ;
        cxChar = tm.tmAveCharWidth ;
        cxCaps = (tm.tmPitchAndFamily & 1 ? 3 : 2) * cxChar / 2 ;
        cyChar = tm.tmHeight + tm.tmExternalLeading ;
        ReleaseDC (hwnd, hdc) ;
        // Save the width of the three columns
        iMaxWidth = 400 * cxChar + 220 * cxCaps ;
        return 1;
    }
    INT Paint()
    {//处理WM_PAINT消息
        INT i=0, x=0, y=0,n=0;
        HDC hdc = BeginPaint (hwnd, &ps) ;
        // Get vertical scroll bar position
        si.cbSize = sizeof (si) ;
        si.fMask  = SIF_POS ;
        GetScrollInfo (hwnd, SB_VERT, &si) ; //获取滚动条信息
        iVertPos = si.nPos ;    // Get horizontal scroll bar position
        GetScrollInfo (hwnd, SB_HORZ, &si) ;
        iHorzPos = si.nPos ;
        // Find painting limits
        iPaintBeg = max (0, iVertPos + ps.rcPaint.top / cyChar) ;
        iPaintEnd = min (i,iVertPos + ps.rcPaint.bottom / cyChar) ;
        x=cxChar*(0-iHorzPos);
        y = cyChar * (1- iVertPos);
        i=0;
        SetTextAlign(hdc,TA_LEFT|TA_TOP);
        for (i = 0; i <9; i++)
        {
            y = 30+cyChar * (3*i- iVertPos) ; //Y坐标
            for(INT j=0;j<=i;j++)
            {
                    x = 50+cxChar * (j*10+j*2 - iHorzPos) ;//X坐标,iHorzPos滚动条位置
    //              x = x+cxChar*lstrlen(pz[i])-iHorzPos;
    //              SetTextAlign (hdc, TA_RIGHT | TA_TOP) ; //输出的对齐方式,现在是右对齐和顶端对齐
                    SetTextAlign (hdc, TA_LEFT | TA_TOP) ;//左对齐,顶端对齐
                    TextOut (hdc, x , y, pz[j],wsprintf(pz[j],"%d × %d = %d ",j+1,i+1,(j+1)*(i+1))-1) ;
            }
        }
        EndPaint (hwnd, &ps) ;
        return 1;
    }
      

  2.   

    if(!hInstance)
    //问题在这里;
            if(!InitApplication(hInstance))//注册窗体
                    return 0;
        if(!InitInstance(hInstance,iCmdShow))//创建并显示更新窗体
            return 0;程序启动时,hInstance肯定不是NULL(0), 所以你的InitAppication(hInstance)没有调用,也就是你的窗口类并没有注册, 后面的当然就失败