📄 winapi.c
字号:
} PostMessage((HWND)pWnd, WM_PAINT, 0, 0); if(pWnd->Children)CM_InvalidateSubWindow(pWnd); } }}
//---------------------------------------------------------------------------
static void CM_OffsetWindow(PWND pWnd,int dx,int dy)
{ OffsetRect(&pWnd->WndRect,dx,dy);
OffsetRect(&pWnd->ClientRect,dx,dy);
if(pWnd->Canvas)
{ TWndCanvas *pCanvas=pWnd->Canvas;
while(pCanvas)
{ pCanvas->VX+=dx;
pCanvas->VY+=dy;
OffsetRect(&pCanvas->ClipRect,dx,dy);
pCanvas=pCanvas->Next;
}
}
if(pWnd->Children)
{ pWnd=pWnd->Children;
while(pWnd)
{ CM_OffsetWindow(pWnd,dx,dy);
pWnd=pWnd->Next;
}
}
}
/////////////////////////////////////////////////////////////
//check if a window area is covered by his brother
////////////////////////////////////////////////////////////
static BOOL CM_WndAreaCoveredByBrother(PWND pWnd,TRECT *area)
{ PWND sibwp=pWnd->Parent->Children;
while(sibwp)
{ if(sibwp!=pWnd && !sibwp->unmapcount)
{ if(RectInRect(area,&sibwp->WndRect))return true;
}
sibwp=sibwp->Next;
}
return false;
}
//---------------------------------------------------------------------------
/*The SetWindowPos function changes the position of the specified window.
For a top-level window, the position are relative to the upper-left corner of the screen.
For a child window, they are relative to the upper-left corner of the parent window's client area.
this function will not change window's z-order
*/
static void CM_SetTopWindowPos(PWND pWnd,int x,int y)
{ PWND sibwp;
TRECT shadowRects[2];
int i,shadowCount,dx,dy;
shadowCount=RectOffsetShadown(shadowRects,&pWnd->WndRect,x,y);
if(!shadowCount)return;
/*erase the shadown when move to new pos*/
if(!pWnd->unmapcount)
{ /*erase background*/
for(i=0;i<shadowCount;i++) RegionUnionRect(&g_RootWnd->Family->Vram->ExposeRegion, &shadowRects[i]);
PostMessage((HWND)g_RootWnd, WM_EXPOSE, 0, 0);
/*only expose low level window in z-order*/
for(i=0;i<shadowCount;i++)
{ sibwp = pWnd;
while (sibwp->Next)
{ sibwp = sibwp->Next;
if(!sibwp->unmapcount && IsRectOverlap(&sibwp->WndRect,&shadowRects[i]))
{ RegionUnionRect(&sibwp->Family->Vram->ExposeRegion, &shadowRects[i]);
PostMessage((HWND)sibwp, WM_EXPOSE, 0, 0);
}
}
}
}
/*calculate window offset*/
dx=x-pWnd->WndRect.left;
dy=y-pWnd->WndRect.top;
/*modify window positon data*/
CM_OffsetWindow(pWnd,dx,dy);
/*resize vram*/
pWnd->Family->Vram->Left=x;
pWnd->Family->Vram->Top=y;
ClearRegion(&pWnd->Family->Vram->ExposeRegion);
/*re-expose window*/
if(!pWnd->unmapcount)
{ RegionUnionRect(&pWnd->Family->Vram->ExposeRegion, &pWnd->WndRect);
PostMessage((HWND)pWnd, WM_EXPOSE, 0, 0);
}
}
//---------------------------------------------------------------------------
static void CM_SetSubWindowPos(PWND pWnd,int x,int y)
{ TRECT shadowRects[2];
int i,shadowCount,dx,dy;
shadowCount=RectOffsetShadown(shadowRects,&pWnd->WndRect,x+pWnd->Parent->ClientRect.left,y+pWnd->Parent->ClientRect.top);
if(!shadowCount)return;
/*erase the shadown when move to new pos*/
if(!pWnd->unmapcount)
{ pWnd->Parent->Family->Vram->GroupOperation++;
for(i=0;i<shadowCount;i++)
{ if(!CM_WndAreaCoveredByBrother(pWnd,&shadowRects[i]))
{ CM_EraseBackgroud(pWnd->Parent, &shadowRects[i]);
}
}
pWnd->Parent->Family->Vram->GroupOperation--;
}
/*calculate window offset*/
dx=x-(pWnd->WndRect.left-pWnd->Parent->ClientRect.left);
dy=y-(pWnd->WndRect.top-pWnd->Parent->ClientRect.top);
/*modify window positon data*/
CM_OffsetWindow(pWnd,dx,dy);
/*re-expose window*/
if(!pWnd->unmapcount)
{ RegionUnionRect(&pWnd->Family->Vram->ExposeRegion, &pWnd->WndRect);
for(i=0;i<shadowCount;i++)
{ RegionUnionRect(&pWnd->Family->Vram->ExposeRegion, &shadowRects[i]);
CM_InvalidateChildren(pWnd->Parent,&shadowRects[i]);
}
CM_InvalidateChildren(pWnd->Parent,&pWnd->WndRect);
PostMessage((HWND)pWnd->Family->TopWnd, WM_EXPOSE, 0, 0);
}
}
//---------------------------------------------------------------------------
void WINAPI SetWindowPos(HWND hWnd, int x,int y)
{ if(IsWnd(hWnd) && WNDPTR(hWnd)->Parent)
{ PWND parentwnd=WNDPTR(hWnd)->Parent;
int oldx=WNDPTR(hWnd)->WndRect.left-parentwnd->ClientRect.left;
int oldy=WNDPTR(hWnd)->WndRect.top-parentwnd->ClientRect.top;
if(x!=oldx || y!=oldy)
{ if(parentwnd==g_RootWnd)
{ CM_SetTopWindowPos((PWND)hWnd,x,y);
}
else
{ CM_SetSubWindowPos((PWND)hWnd,x,y);
}
}
}
}
//---------------------------------------------------------------------------
//re-expose window based on z-order
void WINAPI UpdateWindow(HWND hWnd)
{ if(IsWnd(hWnd) && WNDPTR(hWnd)->unmapcount==0)
{ PWND parentwnd=WNDPTR(hWnd)->Parent;
if(parentwnd==g_RootWnd)
{ CM_ExposeWindow((PWND)hWnd);
}
else if(parentwnd)
{ RegionUnionRect(&WNDPTR(hWnd)->Family->Vram->ExposeRegion, &WNDPTR(hWnd)->WndRect);
CM_InvalidateChildren(parentwnd,&WNDPTR(hWnd)->WndRect);
PostMessage((HWND)WNDPTR(hWnd)->Family->TopWnd, WM_EXPOSE, 0, 0);
}
}
}//---------------------------------------------------------------------------//重绘窗体客户区指定区域*/void WINAPI InvalidateClient(HWND hWnd,TRECT *prc){ if(hWnd && hWnd!=(HWND)g_RootWnd && WNDPTR(hWnd)->unmapcount==0 && prc) { TRECT exposearea; exposearea.left=(prc->left>=0)?prc->left:0; exposearea.right=(prc->right<=crWidth(hWnd))?prc->right:crWidth(hWnd); if(exposearea.left>=exposearea.right)return; exposearea.top=(prc->top>=0)?prc->top:0; exposearea.bottom=(prc->bottom<=crHeight(hWnd))?prc->bottom:crHeight(hWnd); if(exposearea.top>=exposearea.bottom)return; OffsetRect(&exposearea,WNDPTR(hWnd)->ClientRect.left,WNDPTR(hWnd)->ClientRect.top); RegionUnionRect(&WNDPTR(hWnd)->Family->Vram->ExposeRegion, &exposearea); PostMessage(hWnd, WM_PAINT, 0, 0); if(WNDPTR(hWnd)->Children) { CM_InvalidateSubWindow((PWND)hWnd); } }}//---------------------------------------------------------------------------void WINAPI InvalidateWindow(HWND hWnd,BOOL bPaintNC){ PWND pWnd=(PWND)hWnd; if(pWnd && pWnd->unmapcount==0) { RegionUnionRect(&pWnd->Family->Vram->ExposeRegion, &pWnd->WndRect); PostMessage(hWnd, WM_PAINT, 0, 0); if(bPaintNC && WndGetAttr(hWnd,WS_BORDER)) { WndAddAttr(hWnd,WS_NCPAINT); } if(pWnd!=g_RootWnd && pWnd->Children) { CM_InvalidateSubWindow(pWnd); } }}//---------------------------------------------------------------------------void WINAPI Invalidate(HWND hWnd){ InvalidateWindow(hWnd,false);}//---------------------------------------------------------------------------/* * Hide the window to make it and its children invisible on the screen. * This is a recursive routine which increments the unmapcount values for * this window and all of its children, and causes exposure events for * windows which are newly uncovered. */void CM_HideWindow(PWND pWnd,BOOL bChangeFocus, BOOL bSendMsg){ PWND sibwp; /* sibling window */ PWND childwp; /* child window */ pWnd->unmapcount++; /* * Clear the area in the parent for this window, causing an * exposure event for it. */ if (!pWnd->Parent->unmapcount) { if(pWnd->Parent==g_RootWnd) { /*erase background*/ RegionUnionRect(&g_RootWnd->Family->Vram->ExposeRegion, &pWnd->WndRect); PostMessage((HWND)g_RootWnd, WM_EXPOSE, 0, 0); /*only expose low level window in z-order*/ sibwp = pWnd; while (sibwp->Next) { sibwp = sibwp->Next; if(!sibwp->unmapcount && IsRectOverlap(&sibwp->WndRect,&pWnd->WndRect)) { RegionUnionRect(&sibwp->Family->Vram->ExposeRegion, &pWnd->WndRect); PostMessage((HWND)sibwp, WM_EXPOSE, 0, 0); } } } else { RegionUnionRect(&pWnd->Parent->Family->Vram->ExposeRegion, &pWnd->WndRect); PostMessage((HWND)pWnd->Family->TopWnd, WM_EXPOSE, 0, 0); pWnd->Parent->Family->Vram->GroupOperation++; CM_EraseBackgroud(pWnd->Parent, &pWnd->WndRect); pWnd->Parent->Family->Vram->GroupOperation--; CM_InvalidateChildren(pWnd->Parent,&pWnd->WndRect); } } for (childwp = pWnd->Children; childwp; childwp = childwp->Next) { CM_HideWindow(childwp, bChangeFocus, bSendMsg); } if(bSendMsg) SendMessage((HWND)pWnd, WM_SHOWWINDOW, false, 0L); if(bChangeFocus && pWnd==g_CurrentFocus) CM_KillFocus(pWnd);}//---------------------------------------------------------------------------void InvalidateNCArea(HWND hWnd)
{ if(hWnd && WndGetAttr(hWnd,WS_NCPAINT|WS_BORDER)==WS_BORDER)
{ if(WndGetAttr(hWnd,WS_NEEDPAINT))
{ if(RectInRegion(&WNDPTR(hWnd)->Family->Vram->ExposeRegion, &WNDPTR(hWnd)->WndRect))
{ WndAddAttr(hWnd,WS_NCPAINT);
return;
}
}
SendMessage(hWnd,WM_NCPAINT,0,0);
}
}/* * Map the window to possibly make it and its children visible on the screen. * This is a recursive routine which decrements the unmapcount values for * this window and all of its children, and causes exposure events for * those windows which become visible. */void CM_ShowWindow(PWND pWnd, BOOL bSendMsg){ /* * ShowWindow就是暴露一个窗体,暴露时会产生重绘事件 * 如果目标窗口当前在屏幕上可见,ShowWindow会使它及其子窗口再次完完重绘。 * ShowWindow不改变各窗口的层叠关系(Z-ORDER)。 */ if (pWnd->unmapcount) pWnd->unmapcount--; /* * If the window just became visible, * then draw its border, clear it to the background color, and * generate an exposure event. */ if (pWnd->unmapcount == 0) { SendMessage((HWND)pWnd, WM_SHOWWINDOW, true, 0); RegionUnionRect(&pWnd->Family->Vram->ExposeRegion, &pWnd->WndRect); PostMessage((HWND)pWnd, WM_PAINT, 0, 0); if(WndGetAttr(pWnd,WS_BORDER)) WndAddAttr(pWnd,WS_NCPAINT); } /* * Do the same thing for the children. */ for (pWnd = pWnd->Children; pWnd; pWnd = pWnd->Next) { CM_ShowWindow(pWnd, bSendMsg); }}//---------------------------------------------------------------------------BOOL WINAPI ShowWindow(HWND hWnd, BOOL bShow){/*根窗口是特殊的窗口,不允许此操作*/ if(IsWnd(hWnd) && hWnd!=(HWND)g_RootWnd) { if(bShow) { if (WndGetAttr(hWnd,WS_HIDE)) { WndSubAttr(hWnd,WS_HIDE); CM_ShowWindow((PWND)hWnd, true); return true; } else { SetFocus(hWnd); return true; } } else if ( !WndGetAttr(hWnd,WS_HIDE) ) { WndAddAttr(hWnd,WS_HIDE); CM_HideWindow((PWND)hWnd, true,true); return true; } } return false;}/* FUNCTION : EnableWindow * The EnableWindow function enables or disables mouse and keyboard input to the specified window or control. * When input is disabled, the window does not receive input such as mouse clicks and key presses. * When input is enabled, the window receives all input. * If the window was previously disabled, the return value is nonzero. * If the window was not previously disabled, the return value is zero. */BOOL WINAPI EnableWindow(HWND hWnd, BOOL bEnable){ if(bEnable && WndGetAttr(hWnd,WS_DISABLED)) { /* enable window*/ WndSubAttr(hWnd,WS_DISABLED); SendMessage(hWnd, WM_ENABLE, TRUE, 0L); } if(!bEnable && !(WndGetAttr(hWnd,WS_DISABLED)) ) { /* disable window*/ WndAddAttr(hWnd,WS_DISABLED); /* FIXME: handle lost focus for child window of hwnd*/ /* FIXME: handle lost focus for capture window*/ if(hWnd == (HWND)g_CurrentFocus) { CM_KillFocus(hWnd); } SendMessage(hWnd, WM_ENABLE, FALSE, 0L); } return WndGetAttr(hWnd,WS_DISABLED);}
/***************************************************************************
* FUNCTION
* SetTabOrder
* DESCRIPTION
* set window's tabstop order
****************************************************************************/
void SetTabOrder(HWND hWnd,int tabOrder)
{ if(!IsWnd(hWnd))
{ WNDPTR(hWnd)->TabOrder=tabOrder;
}
}
/***************************************************************************
* FUNCTION
* GetTabOrder
* DESCRIPTION
* get window's tabstop order
****************************************************************************/
int GetTabOrder(HWND hWnd)
{ if(!IsWnd(hWnd))
{ return WNDPTR(hWnd)->TabOrder;
}
return -1;
}/*---------------------------------------------------------------------------FUNCTION GetFocusDESCRIPTION 获取键盘输入焦点 This function retrieves the handle of the window that has the keyboard focus---------------------------------------------------------------------------*/HWND WINAPI GetFocus(void){ return (HWND)g_CurrentFocus;}/*---------------------------------------------------------------------------FUNCTION SetFocusDESCRIPTION The SetFocus function sets the keyboard focus to the specified window. The SetFocus function sends a WM_KILLFOCUS message to the window that
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -