第零章:准备好工具先开发一个小程序看看
第一步:找到我们所需要的所有原料
这里用到的原料都是从mingw中获取的,先安装一个mingw然后搜索安装目录找到下面几个文件:
- cc1.exe
- as.exe
- ld.exe
- mingw32-make.exe
- libgmp-10.dll
- libiconv-2.dll
- libintl-8.dll
- libmpc-3.dll
- libmpfr-4.dll
- zlib1.dll
- libgcc_s_dw2-1.dll
当然开发win32程序必不可少的的这几个库文件:
- libgdi32.a
- libkernel32.a
- libuser32.a
找到这14个文件之后,为了不让文件看起来太混乱,新建几个文件目录来存放他们:
把exe文件和dll文件放在tools目录中,a文件放在lib目录中,src目录是为源码准备的目录。
第二步:开始写程序
win32.c
#include "min.h" // 函数的声明、结构体的声明和定义、宏定义
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
/* @@@@ Windows 程序必需1:WinMain函数 */
/* 这个函数相当于控制台程序的main函数 */
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
MSG msg;
HWND hwnd;
static char szAppName[] = "myclass";
/* @@@@ Windows 程序必需2:注册wndclassex */
WNDCLASSEX wndclassex;
wndclassex.cbSize = sizeof(WNDCLASSEX);
wndclassex.cbClsExtra = 0;
wndclassex.cbWndExtra = 0;
wndclassex.hInstance = hInstance;
wndclassex.hIcon = LoadIconA (NULL, IDI_APPLICATION);
wndclassex.hCursor = LoadCursorA (NULL, IDC_ARROW);
wndclassex.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);
wndclassex.lpfnWndProc = WndProc;
wndclassex.lpszMenuName = NULL;
wndclassex.lpszClassName = szAppName;
wndclassex.hIconSm = wndclassex.hIcon;
wndclassex.style = CS_HREDRAW | CS_VREDRAW;
if (!RegisterClassExA (&wndclassex)) {
MessageBoxA (NULL, "RegisterClassEx failed!", szAppName, MB_ICONERROR);
return 0;
}
/* 在这里创建一个窗口并将它显示出来,输出文字的功能是在回调函数中实现的。 */
hwnd = CreateWindowExA (WS_EX_OVERLAPPEDWINDOW, szAppName, "WindowTitle", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
ShowWindow (hwnd, 1);
UpdateWindow (hwnd);
/* @@@@ Windows 程序必需3:消息循环处理 */
while (GetMessageA (&msg, NULL, 0, 0))
{
TranslateMessage (&msg);
DispatchMessageA (&msg);
}
return msg.wParam;
}
/* @@@@ Windows 程序必需4:窗口回调函数 */
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
switch (message)
{
case WM_CREATE:
return 0;
case WM_PAINT:
hdc = BeginPaint (hwnd, &ps);
TextOutA (hdc, 0, 0, "Hello world!", 12);
TextOutA (hdc, 32, 32, "Win32 API!", 9);
EndPaint (hwnd, &ps);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProcA (hwnd, message, wParam, lParam);
}
min.h:
#if (!defined(__stdcall))
#define __stdcall __attribute__((__stdcall__))
#endif
#ifndef NULL
#define NULL ((void*)0)
#endif
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
#ifndef CONST
#define CONST const
#endif
#ifndef VOID
#define VOID void
#endif
typedef unsigned char BYTE;
typedef char CHAR;
typedef short SHORT;
typedef long LONG;
typedef char CCHAR, *PCCHAR;
typedef unsigned char UCHAR,*PUCHAR;
typedef unsigned short USHORT,*PUSHORT;
typedef unsigned long ULONG,*PULONG;
typedef char *PSZ;
typedef void *PVOID,*LPVOID;
typedef unsigned long DWORD;
typedef int WINBOOL,*PWINBOOL,*LPWINBOOL;
typedef WINBOOL BOOL;
typedef BOOL *PBOOL,*LPBOOL;
typedef unsigned short WORD;
typedef float FLOAT;
typedef FLOAT *PFLOAT;
typedef BYTE *PBYTE,*LPBYTE;
typedef int *PINT,*LPINT;
typedef WORD *PWORD,*LPWORD;
typedef long *LPLONG;
typedef DWORD *PDWORD,*LPDWORD;
typedef CONST void *PCVOID,*LPCVOID;
typedef int INT;
typedef unsigned int UINT,*PUINT,*LPUINT;
typedef CHAR TCHAR;
typedef CHAR _TCHAR;
typedef TCHAR TBYTE,*PTCH,*PTBYTE;
typedef TCHAR *LPTCH,*PTSTR,*LPTSTR,*LP,*PTCHAR;
typedef CHAR *PCHAR,*LPCH,*PCH,*NPSTR,*LPSTR,*PSTR;
typedef const TCHAR *LPCTSTR;
typedef int INT_PTR, *PINT_PTR;
typedef unsigned int UINT_PTR, *PUINT_PTR;
typedef long LONG_PTR, *PLONG_PTR;
typedef unsigned long ULONG_PTR, *PULONG_PTR;
typedef const char *LPCCH,*PCSTR,*LPCSTR;
typedef UINT_PTR WPARAM;
typedef LONG_PTR LPARAM;
typedef LONG_PTR LRESULT;
typedef void *HGDIOBJ;
#define MAKEINTRESOURCEA(i) (LPSTR)((DWORD)((WORD)(i)))
#define IDI_APPLICATION MAKEINTRESOURCEA(32512)
#define IDC_ARROW MAKEINTRESOURCEA(32512)
#define WS_EX_OVERLAPPEDWINDOW 0x300
#define WS_BORDER 0x800000
#define WS_CAPTION 0xc00000
#define WS_CHILD 0x40000000
#define WS_CHILDWINDOW 0x40000000
#define WS_CLIPCHILDREN 0x2000000
#define WS_CLIPSIBLINGS 0x4000000
#define WS_DISABLED 0x8000000
#define WS_DLGFRAME 0x400000
#define WS_GROUP 0x20000
#define WS_HSCROLL 0x100000
#define WS_ICONIC 0x20000000
#define WS_MAXIMIZE 0x1000000
#define WS_MAXIMIZEBOX 0x10000
#define WS_MINIMIZE 0x20000000
#define WS_MINIMIZEBOX 0x20000
#define WS_OVERLAPPED 0
#define WS_OVERLAPPEDWINDOW 0xcf0000
#define WS_POPUP 0x80000000
#define WS_POPUPWINDOW 0x80880000
#define WS_SIZEBOX 0x40000
#define WS_SYSMENU 0x80000
#define WS_TABSTOP 0x10000
#define WS_THICKFRAME 0x40000
#define WS_TILED 0
#define WS_TILEDWINDOW 0xcf0000
#define WS_VISIBLE 0x10000000
#define BS_3STATE 5
#define BS_AUTO3STATE 6
#define BS_AUTOCHECKBOX 3
#define BS_AUTORADIOBUTTON 9
#define BS_BITMAP 128
#define BS_BOTTOM 0x800
#define BS_CENTER 0x300
#define BS_CHECKBOX 2
#define BS_DEFPUSHBUTTON 1
#define BS_GROUPBOX 7
#define BS_ICON 64
#define BS_LEFT 256
#define BS_LEFTTEXT 32
#define BS_MULTILINE 0x2000
#define BS_NOTIFY 0x4000
#define BS_OWNERDRAW 0xb
#define BS_PUSHBUTTON 0
#define BS_PUSHLIKE 4096
#define BS_RADIOBUTTON 4
#define BS_RIGHT 512
#define BS_RIGHTBUTTON 32
#define BS_TEXT 0
#define BS_TOP 0x400
#define BS_USERBUTTON 8
#define BS_VCENTER 0xc00
#define BS_FLAT 0x8000
#define WM_SYNCPAINT 136
#define WM_MOUSEACTIVATE 33
#define WM_MOUSEMOVE 512
#define WM_LBUTTONDOWN 513
#define WM_LBUTTONUP 514
#define WM_LBUTTONDBLCLK 515
#define WM_RBUTTONDOWN 516
#define WM_RBUTTONUP 517
#define WM_RBUTTONDBLCLK 518
#define WM_MBUTTONDOWN 519
#define WM_MBUTTONUP 520
#define WM_MBUTTONDBLCLK 521
#define WM_MOUSEWHEEL 522
#define WM_MOUSEFIRST 512
#define CW_USEDEFAULT 0x80000000
#define WHITE_BRUSH 0
#define WM_PAINT 15
#define WM_DESTROY 2
#define MB_ICONERROR 16
#define WM_CREATE 1
#define CS_HREDRAW 2
#define CS_VREDRAW 1
typedef void *HANDLE;
#define DECLARE_HANDLE(n) typedef struct n##__{int i;}*n
DECLARE_HANDLE(HINSTANCE);
DECLARE_HANDLE(HWND);
DECLARE_HANDLE(HMENU);
DECLARE_HANDLE(HICON);
DECLARE_HANDLE(HCURSOR);
DECLARE_HANDLE(HDC);
DECLARE_HANDLE(HBRUSH);
typedef HINSTANCE HMODULE;
#define pascal __stdcall
#define _pascal __stdcall
#define __pascal __stdcall
#define PASCAL _pascal
#define CDECL _cdecl
#define STDCALL __stdcall
#define FASTCALL __fastcall
#define WINAPI __stdcall
#define WINAPIV __cdecl
#define APIENTRY __stdcall
#define CALLBACK __stdcall
#define APIPRIVATE __stdcall
#define UNREFERENCED_PARAMETER(P) {(P)=(P);}
#define UNREFERENCED_LOCAL_VARIABLE(L) {(L)=(L);}
#define DBG_UNREFERENCED_PARAMETER(P)
#define DBG_UNREFERENCED_LOCAL_VARIABLE(L)
typedef long(CALLBACK *WNDPROC)(HWND,UINT,WPARAM,LPARAM);
typedef struct tagRECT {
LONG left;
LONG top;
LONG right;
LONG bottom;
} RECT,*PRECT,*LPRECT;
typedef struct tagPAINTSTRUCT {
HDC hdc;
BOOL fErase;
RECT rcPaint;
BOOL fRestore;
BOOL fIncUpdate;
BYTE rgbReserved[32];
} PAINTSTRUCT,*LPPAINTSTRUCT;
typedef struct _WNDCLASSEXA {
UINT cbSize;
UINT style;
WNDPROC lpfnWndProc;
int cbClsExtra;
int cbWndExtra;
HINSTANCE hInstance;
HICON hIcon;
HCURSOR hCursor;
HBRUSH hbrBackground;
LPCSTR lpszMenuName;
LPCSTR lpszClassName;
HICON hIconSm;
} WNDCLASSEXA,*LPWNDCLASSEXA,*PWNDCLASSEXA;
typedef WNDCLASSEXA WNDCLASSEX,*LPWNDCLASSEX,*PWNDCLASSEX;
typedef struct tagPOINT {
LONG x;
LONG y;
} POINT,POINTL,*PPOINT,*LPPOINT,*PPOINTL,*LPPOINTL;
typedef struct tagMSG {
HWND hwnd;
UINT message;
WPARAM wParam;
LPARAM lParam;
DWORD time;
POINT pt;
} MSG,*LPMSG,*PMSG;
HICON WINAPI LoadIconA(HINSTANCE,LPCSTR);
HCURSOR WINAPI LoadCursorA(HINSTANCE,LPCSTR);
HGDIOBJ WINAPI GetStockObject(int);
WORD WINAPI RegisterClassExA(CONST WNDCLASSEXA*);
BOOL __stdcall GetMessageA(LPMSG,HWND,UINT,UINT);
BOOL __stdcall TranslateMessage(const MSG*);
LONG __stdcall DispatchMessageA(const MSG*);
HWND __stdcall CreateWindowExA(DWORD,LPCSTR,LPCSTR,DWORD,int,int,int,int,HWND,HMENU,HINSTANCE,LPVOID);
BOOL __stdcall ShowWindow(HWND,int);
BOOL __stdcall UpdateWindow(HWND);
int __stdcall MessageBoxA(HWND,LPCSTR,LPCSTR,UINT);
HMODULE __stdcall GetModuleHandleA(LPCSTR);
void WINAPI PostQuitMessage(int);
HDC WINAPI BeginPaint(HWND,LPPAINTSTRUCT);
LRESULT WINAPI DefWindowProcA(HWND,UINT,WPARAM,LPARAM);
BOOL WINAPI EndPaint(HWND,const PAINTSTRUCT*);
BOOL WINAPI TextOutA(HDC,int,int,LPCSTR,int);
BOOL WINAPI LineTo(HDC,int,int);
BOOL WINAPI DestroyWindow(HWND);
BOOL WINAPI CloseWindow(HWND);
VOID WINAPI SwitchToThisWindow(HWND,BOOL);
HANDLE WINAPI GetStdHandle(DWORD);
第三步:编译运行,在src目录下创建下面两个文件
为了方便,写个Makefile让程序自动编译:
TOOLPATH = ../tools/
LIBPATH = ../lib/
DEL = del
CC = $(TOOLPATH)cc1.exe
AS = $(TOOLPATH)as.exe
LD = $(TOOLPATH)ld.exe
MAKE = $(TOOLPATH)mingw32-make.exe
LIBS = $(LIBPATH)libuser32.a $(LIBPATH)libgdi32.a $(LIBPATH)libkernel32.a
win32.exe: win32.o
$(LD) -o win32.exe -Map win32.map win32.o $(LIBS)
%.o: %.s
$(AS) $*.s -o $*.o
%.s: %.c
$(CC) $*.c -o $*.s
clean:
$(DEL) *.o
$(DEL) *.s
$(DEL) *.map
src_only:
$(MAKE) clean
$(DEL) *.exe
再写个批处理(make.bat):
..\tools\mingw32-make.exe -r %1 %2 %3 %4 %5 %6 %7 %8
打开win32.exe来看看:
懒人模式:http://git.oschina.net/hanjianqiao/Windows_win32_API_simple