为了写一个gui,要协调好控件和事件监听的关系以及应用程序不同窗口的关系。 为了要写一个良好支持可扩展的控件库,需要写一个泛化组件库,要写一个泛化组件库,需要先实现它的逻辑基础,也就是可能利用到的几何对象(arith::geo), 为了能够让对组件和窗体的事件监听变得透明,需要封装需要被利用的api和注册窗口类。 现在正在两头开始,这样能够不断测试自己的代码,当上下两部分越来越充实,就自然的结合了. 以下是 os::frame 子库半成品,目的是封装windows application. 代码结构如下: namespace appinfo; 封装应用程序信息. namespace frame; 应用框架. frame::api::def; 常量信息集 frame::api::type; api的基本类型集 frame::api::handle; 封装的句柄集 frame::api::paint; 封装的绘制类,实例化后方便的处理所有跟绘制有关的api. frame::api::mouse; 封装的鼠标信息集 frame::api::message; message处理集 frame::api::proc; form回调函数类,实例化后专门为form池集中处理不同的事件 frame::api::wndclass; 注册窗口类以及窗口相关创建 frame::form; 所有对话框和文档都统一用form类实例化. 由于是两头写,组件库和关键的事件监听框架还没有完全写完,等写到一定阶段再把不同form的事件分开独立处理,
/**//* frame.h :os::frame */
#ifndef APPFRAME__
#define APPFRAME__
#include <windows.h> #include <tchar.h> #include <stdio.h>
#include "axiom.h" #include "string.h" #include "geo.h"
namespace appinfo { static const int max_form=500; static int iCmdShow,regNum,listIndex; static HINSTANCE hInstance; static HINSTANCE hPrevInstance; static PSTR szCmdLine; static MSG msg; /**//* register windowclass-name */ static TCHAR regList[max_form][4]; static void decform() { --regNum; } static void incform() { ++regNum; } static void setListIndex(int & reg_index,LPCWSTR & wc_name) { reg_index=listIndex; regList[listIndex][0]=1; regList[listIndex][1]=reg_index; regList[listIndex][2]=0; wc_name=regList[listIndex]; ++listIndex; ++regNum; }
} namespace frame {
using adt::ustring;
class api { public: class def { public: static const int nil =0; static const int sm_x = 0; static const int sm_y = 1; static const int wm_create=WM_CREATE; static const int wm_paint=WM_PAINT; static const int wm_destroy=WM_DESTROY; static const int wm_mousemove=WM_MOUSEMOVE; static const unsigned int cs_default= CS_HREDRAW | CS_VREDRAW ; }; class type { public: typedef HDC__* hdc; typedef HWND hwnd; typedef ustring string; typedef UINT uint; typedef RECT rect; typedef LPRECT lprc; typedef WPARAM wp; typedef LPCWSTR lpcwstr; typedef LPARAM lp; typedef PAINTSTRUCT ps; typedef LPPAINTSTRUCT lpps; typedef BYTE byte; typedef LONG_PTR result; typedef WNDCLASS wndclass; typedef HICON hicon; typedef HCURSOR hcursor; typedef HBRUSH__* hbrush; typedef HINSTANCE hinstance; typedef PSTR pstr; typedef MSG msg; typedef TCHAR tchar; typedef BOOL state; typedef POINT point; }; class handle {public: static type::hicon icon(int i=0) { return LoadIcon (NULL, IDI_APPLICATION); } static type::hcursor cursor(int i=0) { return LoadCursor (NULL, IDC_ARROW); } static type::hbrush brush(int i=WHITE_BRUSH) { return (type::hbrush) GetStockObject (i); } }; class paint { public: type::hdc hdc; type::rect rect; type::hwnd hwnd; type::ps ps; bool ready; paint():ready(false){} ~paint() { if(ready!=false) end(); ready=false; } type::hdc begin(type::hwnd & hwnd) { ready=true; hdc = BeginPaint(hwnd,&ps); GetClientRect (hwnd, &rect); return (hdc ); } int end() { ready=false; return EndPaint(hwnd,&ps); } int text(type::string & tx) { if(ready) return DrawTextW (hdc, tx(), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER) ; else return 0; } type::state rectangle(int x,int y,int w,int h) { int sx=sm::screenx(); int sy=sm::screeny(); return Rectangle (hdc,x,y,x+w, y+h) ; } type::state polygon(type::point *apt,int i) { return Polygon (hdc,apt,i) ; }
}; class mouse { public: static int x(type::lp & lp) { return LOWORD(lp) ; } static int y(type::lp & lp) { return HIWORD(lp) ;
} }; class sm { public: static int screenx() { return GetSystemMetrics(def::sm_x); } static int screeny() { return GetSystemMetrics(def::sm_y); } }; class message { public: }; class proc { public: type::hwnd hwnd; type::uint msg; type::wp wp; type::lp lp;
proc(){} proc(type::hwnd &hwnd_t,type::uint &msg_t,type::wp &wp_t,type::lp &lp_t) { update(hwnd_t,msg_t,wp_t,lp_t); } void update(type::hwnd &hwnd_t,type::uint &msg_t,type::wp &wp_t,type::lp &lp_t) { hwnd=hwnd_t; msg=msg_t; wp=wp_t; lp=lp_t; } type::result defproc() { return DefWindowProcW (hwnd, msg, wp, lp); }
void postquit(int exitCode_t=0) { if(appinfo::regNum==1) { //WSHOW__(TEXT("啊!是你.")) --appinfo::regNum; PostQuitMessage(exitCode_t); }else { --appinfo::regNum; } }
};
class wndclass { public: type::hwnd hwnd ; type::hwnd parenthwnd; type::string title; type::wndclass wc;/**//* wndclass info */ int regIndex;/**//* self-wndclass index in regList */
static type::result __stdcall wndproc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
static proc proc; static paint pt; static type::string m(TEXT("啊!是你."));
using geo::polygon;
static polygon plg;
static int angle=0; if(angle==0) { plg.push(100,100); plg.push(200,100); plg.push(300,200); plg.push(300,300); plg.push(200,250); plg.push(100,400); angle=1; } static wchar_t buf[20];
proc.update(hwnd,message,wParam,lParam);
switch (message) { case api::def::wm_create: return 0 ; case api::def::wm_mousemove: pt.begin(hwnd); m.set(0); wsprintf(buf,L"(x:%d ,y:%d)\0",mouse::x(lParam),mouse::y(lParam)); m.set(buf);
pt.end(); InvalidateRect(hwnd,NULL,TRUE);
return 0; case api::def::wm_paint: pt.begin(hwnd); { POINT apt[6]; plg.rotate(angle); for(int i=0;i!=6;i++) { apt[i].x=plg(i,0); apt[i].y=plg(i,1); } pt.polygon(apt,6); } pt.text(m);
pt.end();
return 0;
case api::def::wm_destroy: proc.postquit(); return 0 ;
} return proc.defproc(); } void init() { wc.style = def::cs_default; wc.lpfnWndProc = wndproc ; wc.cbClsExtra = def::nil ; wc.cbWndExtra = def::nil ; wc.hInstance = appinfo::hInstance ; wc.hIcon = handle::icon() ; wc.hCursor = handle::cursor(); wc.hbrBackground = handle::brush(); wc.lpszMenuName = def::nil;
appinfo::setListIndex(regIndex,wc.lpszClassName);
if (!RegisterClassW (&wc)) return ; } wndclass() {
init(); } ~wndclass() { appinfo::decform(); } void setStyle(UINT style) { wc.style = style; } void setIcon(HICON hIcon) { wc.hIcon = hIcon; } void setCursor(HCURSOR hCursor) { wc.hCursor = hCursor; } void setBackground(HBRUSH hbr) { wc.hbrBackground = hbr; } int renew() { hwnd = CreateWindowW(appinfo::regList[regIndex], // window class name title(), // window caption WS_OVERLAPPEDWINDOW, // window style CW_USEDEFAULT,// initial x position CW_USEDEFAULT,// initial y position CW_USEDEFAULT,// initial x size CW_USEDEFAULT,// initial y size NULL, // parent window handle NULL, // window menu handle appinfo::hInstance, // program instance handle NULL) ; // creation parameters return 1;
} void setTitle(wchar_t _title[]) { title.set(_title); } }; };
class form { api::wndclass tf; public: form() {
tf.setTitle(TEXT("ving")); tf.init(); tf.renew(); } ~form() { } form(wchar_t *title) { tf.setTitle(title); tf.init(); tf.renew(); }
int show() { tf.renew(); int scx=api::sm::screenx(); int scy=api::sm::screeny(); SetWindowPos(tf.hwnd,NULL,scx/3 ,scx/3 ,scx/3,scy/3,SWP_HIDEWINDOW); ShowWindow (tf.hwnd, appinfo::iCmdShow) ; UpdateWindow (tf.hwnd) ; return 1; } }; } int cpp(); int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,PSTR szCmdLine, int iCmdShow) {
appinfo::regNum=0; appinfo::listIndex=0; appinfo::hInstance=hInstance; appinfo::hPrevInstance=hPrevInstance; appinfo::szCmdLine=szCmdLine; appinfo::iCmdShow=iCmdShow;
cpp();
while (GetMessageW(&appinfo::msg, NULL, 0, 0)) { TranslateMessage (&appinfo::msg) ; DispatchMessage (&appinfo::msg) ; } return (int)appinfo::msg.wParam ; }
#endif
这里是它的入口点界面,在该框架下,入口点是cpp(),当有需要,可以加入隐含变量处理入口点获取的路径和执行参数:
/**//* init.h */
#include "appframe.h"
int cpp() { using frame::form;
form f; f.show();
return 0;
}
当写到一定时机成熟时,会把appframe里的proc form管理池的接口搬到init.h的入口点函数. 由于之前基于自己写的arith::axiom库实现过关于不规则内陷多边形的点区域检测demo,所以接下来关于组件库和监听框架的实现应该会快了. 该代码的demo是一个多边形围绕一个点旋转,中间不停更新鼠标在Client区的相对坐标.
|