一、准备工作
编程语言:C
IDE:Code::Blocks10.05
工程类型:Consoleapplication
代码文件中重复部分不会重复贴出。
1.Windows环境
编译目标配置:
链接库:
gdi32
user32
kernel32
Win_Debug:
加入宏定义
DEBUG
SYSTEM_WIN
Win_Release:
加入宏定义:
SYSTEM_WIN
(1)基本定义和main函数
文件:define.h
#ifndef DEFINE_H_INCLUDED
#define DEFINE_H_INCLUDED
typedef short int16;
typedef int int32;
typedef long long int64;
typedef unsigned short uint16;
typedef unsigned int uint32;
typedef unsigned long long uint64;
#endif // DEFINE_H_INCLUDED
在该文件中目前定义了最基本的几个数据类型。基本上工程中所有文件都要包含这个头文件。
文件:gui.h
#ifndef GUI_H_INCLUDED
#define GUI_H_INCLUDED
#if defined(SYSTEM_WIN)
#include "gui_windows.h"
#endif
#endif // GUI_H_INCLUDED
图形界面实现的选择,在定义了SYSTEM_WIN的情况下直接用Windows的API编程。
文件:gui_windows.h
#ifndef GUI_WINDOWS_H_INCLUDED
#define GUI_WINDOWS_H_INCLUDED
#include <windows.h>
#include "define.h"
#define main fake_main
int WINAPI WinMain(HINSTANCE, HINSTANCE, PSTR, int);
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
#endif // GUI_WINDOWS_H_INCLUDED
因为windows的程序入口是WinMain(...),这里使用了宏定义,当写main函数的时候会被改名为fake_main,而在WinMain中调用fake_main函数,这样就可以像平常一样写main函数,而不用管GUI的实现了。
文件:gui_windows.c
#include "gui_windows.h"
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
PSTR szCmdLine,
int iCmdShow)
{
fake_main();
return 0;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
}
目前还没写实际的东西。
(2)主窗口的创建
文件:gui_windows.h
#ifndef GUI_WINDOWS_H_INCLUDED
#define GUI_WINDOWS_H_INCLUDED
#include <windows.h>
#include "define.h"
#define main fake_main
int fake_main();
int WINAPI WinMain(HINSTANCE, HINSTANCE, PSTR, int);
LRESULT CALLBACK gui_mainProcess(HWND, UINT, WPARAM, LPARAM);
void gui_createMainWindow(const char *);
void gui_mainLoop();
#endif // GUI_WINDOWS_H_INCLUDED
文件:gui_windows.c
#include "gui_windows.h"
static HINSTANCE mainInstance;
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
PSTR szCmdLine,
int iCmdShow)
{
mainInstance = hInstance;
return fake_main();
}
void gui_createMainWindow(const char *title)
{
WNDCLASS mainWindow;
mainWindow.style = CS_HREDRAW | CS_VREDRAW;
mainWindow.lpfnWndProc = gui_mainProcess;
mainWindow.cbClsExtra = 0;
mainWindow.cbWndExtra = 0;
mainWindow.hInstance = mainInstance;
mainWindow.hIcon = LoadIcon(NULL, IDI_APPLICATION);
mainWindow.hCursor = LoadCursor(NULL, IDC_ARROW);
mainWindow.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
mainWindow.lpszMenuName = NULL;
mainWindow.lpszClassName = "mainWindow";
if(!RegisterClass(&mainWindow))
{
MessageBox(NULL, TEXT("Cannot register class for main window."), TEXT(title), MB_ICONERROR);
exit(0);
}
HWND handleMainWindow;
handleMainWindow = CreateWindow("mainWindow",
title,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
mainInstance,
NULL);
ShowWindow(handleMainWindow, 1);
UpdateWindow(handleMainWindow);
}
void gui_mainLoop()
{
MSG message;
while(GetMessage(&message, NULL, 0, 0))
{
TranslateMessage(&message);
DispatchMessage(&message);
}
}
LRESULT CALLBACK gui_mainProcess(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc ;
PAINTSTRUCT ps ;
RECT rect ;
switch (message)
{
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
GetClientRect(hwnd, &rect);
EndPaint(hwnd, &ps) ;
break;
case WM_DESTROY:
PostQuitMessage(0) ;
break;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
文件:main.c
#include <stdio.h>
#include <stdlib.h>
#include "gui.h"
int main()
{
gui_createMainWindow("ZPIC");
gui_mainLoop();
return 0;
}
由于与图形学无关,这里只需知道在main函数中使用这两个函数就可以创建主窗口了。
(3)主窗口的基本参数设置
文件:gui_windows.h
#ifndef GUI_WINDOWS_H_INCLUDED
#define GUI_WINDOWS_H_INCLUDED
#include <assert.h>
#include <windows.h>
#include "define.h"
#define main fake_main
void gui_setMainWindowPosition(int32 x, int32 y);
void gui_setMainWindowSize(int32 w, int32 h);
void gui_setMainWindowToCenter();
void gui_setMainWindowMinimize();
void gui_setMainWindowMaximize();
void gui_setMainWindowRestore();
#endif // GUI_WINDOWS_H_INCLUDED
文件:gui_windows.c
#include "gui_windows.h"
static HINSTANCE mainInstance;
static HWND handleMainWindow;
static int32 systemWidth, systemHeight;
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
PSTR szCmdLine,
int iCmdShow)
{
mainInstance = hInstance;
systemWidth = GetSystemMetrics(SM_CXSCREEN);
systemHeight = GetSystemMetrics(SM_CYSCREEN);
return fake_main();
}
void gui_setMainWindowPosition(int32 x, int32 y)
{
assert(handleMainWindow != NULL);
SetWindowPos(handleMainWindow, NULL, x, y, 0, 0, SWP_NOSIZE);
}
void gui_setMainWindowSize(int32 w, int32 h)
{
assert(handleMainWindow != NULL);
SetWindowPos(handleMainWindow, NULL, 0, 0, w, h, SWP_NOMOVE);
}
void gui_setMainWindowToCenter()
{
assert(handleMainWindow != NULL);
RECT rect;
GetWindowRect(handleMainWindow, &rect);
int32 w = rect.right - rect.left;
int32 h = rect.bottom - rect.top;
gui_setMainWindowPosition((systemWidth - w) >> 1, (systemHeight - h) >> 1);
}
void gui_setMainWindowMinimize()
{
assert(handleMainWindow != NULL);
SendMessage(handleMainWindow, WM_SYSCOMMAND, SC_MINIMIZE, (LPARAM)NULL);
}
void gui_setMainWindowMaximize()
{
assert(handleMainWindow != NULL);
SendMessage(handleMainWindow, WM_SYSCOMMAND, SC_MAXIMIZE, (LPARAM)NULL);
}
void gui_setMainWindowRestore()
{
assert(handleMainWindow != NULL);
SendMessage(handleMainWindow, WM_SYSCOMMAND, SC_RESTORE, (LPARAM)NULL);
}
文件:main.c
#include <stdio.h>
#include <stdlib.h>
#include "gui.h"
int main()
{
#ifndef DEBUG
freopen("log.txt", "w", stdout);
#endif
freopen("error.txt", "w", stderr);
gui_createMainWindow("ZPIC");
gui_setMainWindowSize(800, 600);
gui_setMainWindowToCenter();
gui_setMainWindowMaximize();
gui_mainLoop();
return 0;
}
由于与图形学无关,这里只需知道函数名及相应功能即可。
(4)基本消息获取结构
文件:gui_windows.h
void gui_setDisplayFunction(void (*func)(void));
void gui_setReshapeFunction(void (*func)(int32 w, int32 h));
void gui_setKeyboardFunction(void (*func)(unsigned char key, int32 x, int32 y));
void gui_setMouseFunction(void (*func)(int32 button, int32 state, int32 x, int32 y));
void gui_setMotionFunction(void (*func)(int32 x, int32 y));
文件:gui_windows.c
static void (*mainWindowDisplayFunction)();
static void (*mainWindowReshapeFunction)(int32, int32);
static void (*mainWindowKeyboardFunction)(unsigned char, int32, int32);
static void (*mainWindowMouseFunction)(int32, int32, int32, int32);
static void (*mainWindowMotionFunction)(int32, int32);
void gui_setDisplayFunction(void (*func)(void))
{
mainWindowDisplayFunction = func;
}
void gui_setReshapeFunction(void (*func)(int32 w, int32 h))
{
mainWindowReshapeFunction = func;
}
void gui_setKeyboardFunction(void (*func)(unsigned char key, int32 x, int32 y))
{
mainWindowKeyboardFunction = func;
}
void gui_setMouseFunction(void (*func)(int32 button, int32 state, int32 x, int32 y))
{
mainWindowMouseFunction = func;
}
void gui_setMotionFunction(void (*func)(int32 x, int32 y))
{
mainWindowMotionFunction = func;
}
文件:main.c
#include <stdio.h>
#include <stdlib.h>
#include "define.h"
#include "gui.h"
void displayFunction(void)
{
//TODO
}
void reshapeFunction(int32 w, int32 h)
{
//TODO
}
void keyboardFunction(unsigned char key, int32 x, int32 y)
{
//TODO
}
void mouseFunction(int32 button, int32 state, int32 x, int32 y)
{
//TODO
}
void motionFunction(int32 x, int32 y)
{
//TODO
}
int main()
{
#ifndef DEBUG
freopen("log.txt", "w", stdout);
#endif
freopen("error.txt", "w", stderr);
gui_createMainWindow("ZPIC");
gui_setMainWindowSize(800, 600);
gui_setMainWindowToCenter();
gui_setDisplayFunction(displayFunction);
gui_setReshapeFunction(reshapeFunction);
gui_setKeyboardFunction(keyboardFunction);
gui_setMouseFunction(mouseFunction);
gui_setMotionFunction(motionFunction);
gui_mainLoop();
return 0;
}
(5)基本绘制条件
添加上鼠标事件的监控和像素点的绘制后,就满足了基本的学习条件。
文件:define.h
typedef uint16 z_color;
static const int32 MOUSE_LEFT = 0;
static const int32 MOUSE_MIDDLE = 1;
static const int32 MOUSE_RIGHT = 2;
static const int32 MOUSE_DOWN = 3;
static const int32 MOUSE_UP = 4;
文件:gui_windows.h
void gui_repaint(void);
void gui_setPixel(int x, int y, int r, int g, int b);
z_color gui_getPixel(int x, int y);
文件:gui_windows.c
void gui_repaint(void)
{
InvalidateRect(handleMainWindow, NULL, TRUE);
UpdateWindow(handleMainWindow);
}
void gui_setPixel(int x, int y, int r, int g, int b)
{
COLORREF color = RGB(r, g, b);
SetPixel(handleMainWindowDeviceContext, x, y, color);
}
z_color gui_getPixel(int x, int y)
{
return GetPixel(handleMainWindowDeviceContext, x, y);
}
LRESULT CALLBACK gui_mainProcess(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
RECT rect;
switch (message)
{
case WM_PAINT:
handleMainWindowDeviceContext = BeginPaint(hwnd, &ps);
GetClientRect(hwnd, &rect);
if(mainWindowDisplayFunction)
{
mainWindowDisplayFunction();
}
EndPaint(hwnd, &ps) ;
break;
case WM_MOUSEMOVE:
if(mainWindowMotionFunction)
{
mainWindowMotionFunction(LOWORD(lParam), HIWORD(lParam));
}
break;
case WM_LBUTTONDOWN:
if(mainWindowMouseFunction)
{
mainWindowMouseFunction(MOUSE_LEFT, MOUSE_DOWN, LOWORD(lParam), HIWORD(lParam));
}
break;
case WM_LBUTTONUP:
if(mainWindowMouseFunction)
{
mainWindowMouseFunction(MOUSE_LEFT, MOUSE_UP, LOWORD(lParam), HIWORD(lParam));
}
break;
case WM_RBUTTONDOWN:
if(mainWindowMouseFunction)
{
mainWindowMouseFunction(MOUSE_RIGHT, MOUSE_DOWN, LOWORD(lParam), HIWORD(lParam));
}
break;
case WM_RBUTTONUP:
if(mainWindowMouseFunction)
{
mainWindowMouseFunction(MOUSE_RIGHT, MOUSE_UP, LOWORD(lParam), HIWORD(lParam));
}
break;
case WM_MBUTTONDOWN:
if(mainWindowMouseFunction)
{
mainWindowMouseFunction(MOUSE_MIDDLE, MOUSE_DOWN, LOWORD(lParam), HIWORD(lParam));
}
break;
case WM_MBUTTONUP:
if(mainWindowMouseFunction)
{
mainWindowMouseFunction(MOUSE_MIDDLE, MOUSE_UP, LOWORD(lParam), HIWORD(lParam));
}
break;
case WM_KEYDOWN:
break;
case WM_KEYUP:
break;
case WM_MOUSEWHEEL:
break;
case WM_DESTROY:
PostQuitMessage(0) ;
break;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
查看完整代码:http://blog.csdn.net/cyberzhg/article/details/7720282