Chinaunix首页 | 论坛 | 博客
  • 博客访问: 512771
  • 博文数量: 95
  • 博客积分: 5168
  • 博客等级: 大校
  • 技术积分: 1271
  • 用 户 组: 普通用户
  • 注册时间: 2008-12-28 23:31
文章分类

全部博文(95)

文章存档

2013年(2)

2012年(3)

2011年(1)

2010年(8)

2009年(81)

分类:

2009-01-13 13:04:17

魏永明
蓝点软件(北京)研发中心技术主管


图 1 由四个矩形组成的桌面剪切域


图 2 由两个矩形组成的桌面剪切域


图 3 有新窗口被创建时,桌面和旧窗口的剪切域

清单 1  显示新窗口时计算被新窗口覆盖的窗口的全局剪切域

// clip all windows under this window.
static void clip_windows_under_this (ZORDERINFO* zorder, PMAINWIN pWin, RECT* rcWin)
{
PZORDERNODE pNode;
PGCRINFO pGCRInfo;

pNode = zorder->pTopMost;
while (pNode->hWnd != (HWND)pWin)
pNode = pNode->pNext;
pNode = pNode->pNext;

while (pNode)
{
if (((PMAINWIN)(pNode->hWnd))->dwStyle & WS_VISIBLE) {
pGCRInfo = ((PMAINWIN)(pNode->hWnd))->pGCRInfo;

pthread_mutex_lock (&pGCRInfo->lock);
SubtractClipRect (&pGCRInfo->crgn, rcWin);
pGCRInfo->age ++;
pthread_mutex_unlock (&pGCRInfo->lock);
}

pNode = pNode->pNext;
}
}

清单 2  从剪切矩形私有堆中分配和释放剪切矩形

PCLIPRECT GUIAPI ClipRectAlloc(PFREECLIPRECTLIST pList)
{
PCLIPRECT pRect;

#ifndef _LITE_VERSION
pthread_mutex_lock (&pList->lock);
#endif

if (pList->head) {
pRect = pList->head;
pList->head = pRect->next;
}
else {

if (pList->free < pList->size) {
pRect = pList->heap + pList->free;
pRect->fromheap = TRUE;
pList->free ++;
}
else {
pRect = malloc (sizeof(CLIPRECT));
if (pRect == NULL)
fprintf (stderr, "GDI error: alloc clip rect failure!\n");
else
pRect->fromheap = FALSE;
}
}

#ifndef _LITE_VERSION
pthread_mutex_unlock (&pList->lock);
#endif

return pRect;
}

void GUIAPI FreeClipRect(PFREECLIPRECTLIST pList, CLIPRECT* pRect)
{
#ifndef _LITE_VERSION
pthread_mutex_lock (&pList->lock);
#endif

pRect->next = NULL;
if (pList->head) {
pList->tail->next = (PCLIPRECT)pRect;
pList->tail = (PCLIPRECT)pRect;
}
else {
pList->head = pList->tail = (PCLIPRECT)pRect;
}

#ifndef _LITE_VERSION
pthread_mutex_unlock (&pList->lock);
#endif
}

清单 4  控件的子类化

#define IDC_CTRL1 100
#define IDC_CTRL2 110
#define IDC_CTRL3 120
#define IDC_CTRL4 130

#define MY_ES_DIGIT_ONLY 0x0001
#define MY_ES_ALPHA_ONLY 0x0002
static WNDPROC old_edit_proc;
static int RestrictedEditBox (HWND hwnd, int message, WPARAM wParam, LPARAM lParam)
{
if (message == MSG_CHAR) {
DWORD my_style = GetWindowAdditionalData (hwnd);

/* 确定被屏蔽的按键类型 */
if ((my_style & MY_ES_DIGIT_ONLY) && (wParam < '0' || wParam > '9'))
return 0;
else if (my_style & MY_ES_ALPHA_ONLY)
if (!((wParam >= 'A' && wParam <= 'Z') || (wParam >= 'a' && wParam <= 'z')))
/* 收到被屏蔽的按键消息,直接返回 */
return 0;
}

/* 由老的窗口过程处理其余消息 */
return (*old_edit_proc) (hwnd, message, wParam, lParam);
}

static int ControlTestWinProc (HWND hWnd, int message, WPARAM wParam, LPARAM lParam)
{
switch (message) {
case MSG_CREATE:
{
HWND hWnd1, hWnd2, hWnd3;

CreateWindow (CTRL_STATIC, "Digit-only box:", WS_CHILD | WS_VISIBLE | SS_RIGHT, 0,
10, 10, 180, 24, hWnd, 0);
hWnd1 = CreateWindow (CTRL_EDIT, "", WS_CHILD | WS_VISIBLE | WS_BORDER, IDC_CTRL1,
200, 10, 180, 24, hWnd, MY_ES_DIGIT_ONLY);
CreateWindow (CTRL_STATIC, "Alpha-only box:", WS_CHILD | WS_VISIBLE | SS_RIGHT, 0,
10, 40, 180, 24, hWnd, 0);
hWnd2 = CreateWindow (CTRL_EDIT, "", WS_CHILD | WS_BORDER | WS_VISIBLE, IDC_CTRL2,
200, 40, 180, 24, hWnd, MY_ES_ALPHA_ONLY);
CreateWindow (CTRL_STATIC, "Normal edit box:", WS_CHILD | WS_VISIBLE | SS_RIGHT, 0,
10, 70, 180, 24, hWnd, 0);
hWnd3 = CreateWindow (CTRL_EDIT, "", WS_CHILD | WS_BORDER | WS_VISIBLE, IDC_CTRL2,
200, 70, 180, 24, hWnd, MY_ES_ALPHA_ONLY);

CreateWindow ("button", "Close", WS_CHILD | BS_PUSHBUTTON | WS_VISIBLE, IDC_CTRL4,
100, 100, 60, 24, hWnd, 0);

/* 用自定义的窗口过程替换编辑框的窗口过程,并保存老的窗口过程。*/
old_edit_proc = SetWindowCallbackProc (hWnd1, RestrictedEditBox);
SetWindowCallbackProc (hWnd2, RestrictedEditBox);
break;
}

...
}

return DefaultMainWinProc (hWnd, message, wParam, lParam);
}

#define MAXLEN_CLASSNAME    15
typedef struct _CTRLCLASSINFO
{
char name [MAXLEN_CLASSNAME + 1];
// 控件类名程
/*
* common properties of this class
*/
DWORD dwStyle; // 控件类风格

HCURSOR hCursor; // 控件光标
int iBkColor; // 控件的背景颜色

int (*ControlProc)(HWND, int, WPARAM, LPARAM);
// 控件处理过程

DWORD dwAddData; // 附加数据

int nUseCount; // 使用计数,即系统中属于该控件类的控件个数
struct _CTRLCLASSINFO* next;
// 下一个控件类信息结构
} CTRLCLASSINFO;
typedef CTRLCLASSINFO* PCTRLCLASSINFO;

static int HashFunc (char* szClassname)
{
/* 判断首字符是否为字母 */
if (!isalpha (szClassName[0])) return ERR_CTRLCLASS_INVNAME;

/* 讲所有字符转换为大写 */
while (szClassName[i]) {
szClassName[i] = toupper(szClassName[i]);

i++;
if (i > MAXLEN_CLASSNAME)
return ERR_CTRLCLASS_INVLEN;
}

/* 获得哈希值 */
return szClassName[0] - 'A';
}

typedef struct _CONTROL
{
/*
* 这些成员和 MAINWIN 结构一致.
*/
short DataType; // 内部使用的数据类型
short WinType; // 内部使用的窗口类型

int left, top; // 控件在父窗口中的位置
int right, bottom;

int cl, ct; // 控件客户区在父窗口中的位置
int cr, cb;

DWORD dwStyle; // 控件风格
DWORD dwExStyle; // 控件扩展风格

int iBkColor; // 背景颜色
HMENU hMenu; // 菜单句柄
HACCEL hAccel; // 加速键表句柄
HCURSOR hCursor; // 鼠标光标句柄
HICON hIcon; // 图标句柄
HMENU hSysMenu; // 系统菜单句柄

HDC privCDC; // 私有 DC 句柄
INVRGN InvRgn; // 控件的无效区域
PGCRINFO pGCRInfo; // 控件的全局剪切区域
PZORDERNODE pZOrderNode;
// Z 序节点
// 仅对具有 WS_EX_CTRLASMAINWIN 扩展风格的控件有效

PCARETINFO pCaretInfo; // 插入符消息

DWORD dwAddData; // 控件附加数据
DWORD dwAddData2; // 控件附加数据

int (*ControlProc) (HWND, int, WPARAM, LPARAM); // 控件消息处理过程

char* spCaption; // 控件标题
int id; // 控件标识符,整数

SCROLLBARINFO vscroll; // 垂直滚动条信息
SCROLLBARINFO hscroll; // 水平滚动条信息

PMAINWIN pMainWin; // 包含该控件的主窗口

struct _CONTROL* pParent;// 控件的父窗口

/*
* Child windows.
*/
struct _CONTROL* children;
// 控件的第一个子控件
struct _CONTROL* active;
// 当前活动子控件
struct _CONTROL* old_under_pointer;
// 老的鼠标鼠标所在子控件
/*
* 下面这些成员只对控件有效
*/
struct _CONTROL* next; // 下一个兄弟控件
struct _CONTROL* prev; // 前一个兄弟控件

PCTRLCLASSINFO pcci; // 指向控件所属控件类结构的指针

} CONTROL;
typedef CONTROL* PCONTROL;

    阅读(2334) | 评论(0) | 转发(0) |
    给主人留下些什么吧!~~