再Linux上编译Windows程序

主要是通过mingw-w64来实现。

  • i686-w64-mingw32 用于32位程序的编译
  • x86_64-w64-mingw32 用于64位程序的编译

入口函数

Windows图形程序的入口一般是WinMain()。但在Mingw中还是使用main()作为入口函数。

编译Windows程序

典型的编译命令为

x86_64-w64-mingw32-gcc -mwindows program.c
  • -mwindows表明是编译图形窗口程序。
  • -mindows对应的是-mconsole
  • -mindows-mconsole不是互斥的,是可以一起用的。
  • 可以用-m32-m64显示指定编译32位程序还是64位程序。

更多编译参数参见x86 Windows Options

Windows图形窗口程序示例

  • 下面的程序示例创建一个基本的Window程序窗口
  • main()作为入口函数,创建参数后,调用WinMain()函数
  • 编译后的文件大小是16KB左右(使用了-s参数)
#include <windows.h>

LRESULT CALLBACK WindowProcedure(
  HWND hWnd,
  UINT message,
  WPARAM wParam,
  LPARAM lParam
){
  switch(message){
    case WM_CREATE:
      return 0;
    case WM_CLOSE:
      PostQuitMessage(0);
      break;
    case WM_COMMAND:
    case WM_APP:
      break;
  }
  return DefWindowProc(hWnd, message, wParam, lParam);
}

int RegisterWindowClass(HINSTANCE hInstance, const char *className){

  WNDCLASSEX wclx;
  memset(&wclx, 0, sizeof(WNDCLASSEX));

  wclx.cbSize        = sizeof(WNDCLASSEX);
  wclx.hInstance     = hInstance;
  wclx.lpszClassName = className;
  wclx.lpfnWndProc   = WindowProcedure;   /* Message Callback */
  wclx.style         = 0;

  wclx.hCursor       = LoadCursor(NULL, IDC_ARROW);
  wclx.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1);
  wclx.lpszMenuName  = NULL;
  wclx.cbClsExtra    = 0;           /* Extra bytes after the window class */
  wclx.cbWndExtra    = 0;           /* Extra structure or window instance */

  // wclx.hIcon   = LoadIcon(hInstance, MAKEINTRESOURCE(ICO1));
  // wclx.hIconSm = LoadIcon(hInstance, MAKEINTRESOURCE(ICO1));


  if( !RegisterClassEx(&wclx) ){
    MessageBox(NULL,
        "can not create window class",
        "aha",
        MB_ICONERROR | MB_OK | MB_TOPMOST);
    return 0;
  }
  return 1;
}

int WinMain(
  HINSTANCE hInstance,
  HINSTANCE hPrevInstance,
  LPSTR     lpCmdLine,
  int       nCmdShow
){

  /* 1. Register Window Class */
  const char *szClassName = "Mingw Windows Demo";

  RegisterWindowClass(hInstance, szClassName);

  /* 2. Create Window */

  HWND hWnd = CreateWindowEx(
            0,                   /* Extended possibilites for variation */
            szClassName,         /* Classname */
            szClassName,         /* Title Text */
            WS_OVERLAPPEDWINDOW, /* default window */
            CW_USEDEFAULT,       /* Windows decides the position */
            CW_USEDEFAULT,       /* where the window ends up on the screen */
            544,                 /* The programs width */
            375,                 /* and height in pixels */
            HWND_DESKTOP,        /* The window is a child-window to desktop */
            NULL,                /* No menu */
            hInstance,           /* Program Instance handler */
            NULL                 /* No Window Creation data */
  );

  ShowWindow(hWnd, nCmdShow);
  /* 3. Message Loop */

  MSG message;
  while (GetMessage(&message, NULL, 0, 0)){
    TranslateMessage(&message);
    DispatchMessage(&message);
  }

  /* 4. Clean up */
  UnregisterClass(szClassName, hInstance);

  return message.wParam;
}

int main(int argc, char *argv[]){
  /* 0. Prepare WinMain Parameters */
  HINSTANCE hInstance     = GetModuleHandle(NULL);
  HINSTANCE hPrevInstance = NULL;
  LPSTR     lpCmdLine;
  int       nCmdShow = SW_SHOW;

  return WinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
};