📄 win.c
字号:
// 向系统分配一个绘图DC
// 引用:
// 系统API
// ************************************************
HDC WINAPI WinGdi_GetDCEx(HWND hWnd, HRGN hrgn, DWORD flags)
{
_LPWINDATA lpws;
HRGN hrgnExpose, hrgnDraw;
RECT rect;
HDC hdc;
if( hWnd == NULL || hWnd == hwndScreen.hThis )
{ //屏幕窗口,得到一个全屏幕的DC
rect = hwndScreen.rectWindow;
hrgnDraw = WinRgn_CreateRect( rect.left, rect.top, rect.right, rect.bottom );
hdc = GetPaintDC( hWnd, &rect, hrgnDraw, flags | DCF_GETDC_ALLOC );
#ifdef EML_DOS
_HideMouse();
#endif
return hdc;
}
lpws = _GetHWNDPtr( hWnd );
if( lpws )
{ //有效
if( flags & DCX_WINDOW )
rect = lpws->rectWindow; //用窗口矩形
else
{ //用客户区矩形
rect = lpws->rectClient;
OffsetRect( &rect, lpws->rectWindow.left, lpws->rectWindow.top );
}
//初始化裁剪区
hrgnDraw = WinRgn_CreateRect( 0, 0, 0, 0 );
ASSERT( hrgnDraw );
if( IS_SHOWENABLE( lpws->dwMainStyle ) ) //为 ShowDesktop修改
{ //得到窗口的爆露矩形
GetExposeRgn( hWnd, flags, &hrgnExpose );
ASSERT( hrgnExpose );
// hrgn是client 坐标, 偏移到screen
if( hrgn )
{
WinRgn_Offset( hrgn, rect.left, rect.top );
}
if( flags & DCX_EXCLUDERGN ) //需要排除 hrgn吗 ?
WinRgn_Combine( hrgnDraw, hrgnExpose, hrgn, RGN_DIFF );
else if( flags & DCX_INTERSECTRGN ) //需要内交 hrgn吗 ?
WinRgn_Combine( hrgnDraw, hrgnExpose, hrgn, RGN_AND );
else //需要拷贝 hrgn吗 ?
WinRgn_Combine( hrgnDraw, hrgnExpose, 0, RGN_COPY );
if( flags & DCX_VALIDATE ) //是否需要更新系统裁剪区
{ // exlude hrgnExpose from update region
if( flags & DCX_INTERSECTUPDATE )
WinRgn_Combine( hrgn, hrgn, hrgnExpose, RGN_DIFF );
}
// 恢复hrgn的原始状态
if( hrgn )
{
WinRgn_Offset( hrgn, -rect.left, -rect.top );
}
WinGdi_DeleteObject( hrgnExpose );
}
//向系统申请/并初始化一个DC对象
hdc = GetPaintDC( hWnd, &rect, hrgnDraw, flags | DCF_GETDC_ALLOC );
#ifdef EML_DOS
_HideMouse();
#endif
return hdc;
}
return 0;
}
// **************************************************
// 声明:HDC WINAPI WinGdi_GetClientDC( HWND hWnd )
// 参数:
// IN hWnd-窗口句柄
// 返回值:
// 成功:返回该窗口客户区DC句柄
// 否则:返回NULL
// 功能描述:
// 得到客户区DC
// 引用:
// 系统 API
// ************************************************
HDC WINAPI WinGdi_GetClientDC( HWND hWnd )
{
return WinGdi_GetDCEx( hWnd, 0, DCX_CLIPSIBLINGS | DCX_CLIPCHILDREN );
}
// **************************************************
// 声明:HDC WINAPI WinGdi_GetWindowDC( HWND hWnd )
// 参数:
// IN hWnd-窗口句柄
// 返回值:
// 成功:返回该窗口DC句柄
// 否则:返回NULL
// 功能描述:
// 得到窗口DC
// 引用:
// 系统API
// ************************************************
HDC WINAPI WinGdi_GetWindowDC( HWND hWnd )
{
return WinGdi_GetDCEx( hWnd, 0, DCX_CLIPSIBLINGS | DCX_WINDOW );
}
// **************************************************
// 声明:HDC WINAPI WinGdi_BeginPaint( HWND hWnd, LPPAINTSTRUCT lpPaint )
// 参数:
// IN hWnd-窗口句柄
// IN lpps-PAINTSTRUCT 结构指针
// 返回值:
// 成功:返回该窗口DC句柄
// 否则:返回NULL
// 功能描述:
// 准备窗口的绘图数据,并返回DC句柄
// 引用:
// 系统API
// ************************************************
HDC WINAPI WinGdi_BeginPaint( HWND hWnd, LPPAINTSTRUCT lpPaint )
{
_LPWINDATA lpws = _GetHWNDPtr( hWnd );
DWORD flags = 0;
HRGN hrgn, hrgnUpdate, hrgnRemove;
RECT rc;
if( lpws )
{ //根据风格得到相关的 DC
if( lpws->dwMainStyle & WS_CLIPSIBLINGS )
flags |= DCX_CLIPSIBLINGS;
if( lpws->dwMainStyle & WS_CLIPCHILDREN )
flags |= DCX_CLIPCHILDREN;
if( !(lpws->dwMainStyle & WS_CHILD) )
flags |= DCX_CLIPSIBLINGS;
if( lpws->dwMainStyle & WS_CHILD )
flags |= DCX_WINDOW;
flags |= DCX_VALIDATE | DCX_INTERSECTUPDATE;
//清除该窗口的 WM_PAINT消息
ClearThreadQueue( 0, hWnd, WM_PAINT, WM_PAINT );
//EnterCriticalSection( &csWindow );
//进入冲突段
LockCSWindow(); //2004-12-28
//得到该窗口的暴露区域
GetExposeRgn( hWnd, flags, &hrgnUpdate );
//得到窗口区域
GetExposeRgn( hWnd, DCX_CLIPCHILDREN | DCX_WINDOW | flags, &hrgnRemove );
UnlockCSWindow(); //2004-12-28
//锁住系统无效区域
__LockRepaintRgn( &hrgn ); // 2003.1.25
//窗口暴露区域与系统无效区域做内交
WinRgn_Combine( hrgnUpdate, hrgnUpdate, hrgn, RGN_AND );
//从系统无效区清除窗口区域
WinRgn_Combine( hrgn, hrgn, hrgnRemove, RGN_DIFF );
//解锁系统无效区域
__UnlockRepaintRgn(); //2003.1.25
WinGdi_DeleteObject(hrgnRemove);
if( lpws->dwMainStyle & WS_CHILD )
{ //子窗口
//得到裁剪区矩形
WinRgn_GetBox(hrgnUpdate, &rc);
//转化到客户坐标
OffsetRect( &rc, -lpws->rectWindow.left, -lpws->rectWindow.top );
if( !(rc.left >= lpws->rectClient.left &&
rc.top >= lpws->rectClient.top &&
rc.right <= lpws->rectClient.right &&
rc.bottom <= lpws->rectClient.bottom) )
{
HRGN hrgnNC;
int xOffset = lpws->rectWindow.left;
int yOffset = lpws->rectWindow.top;
// hrgn是screen 坐标, 偏移到client
WinRgn_Offset( hrgnUpdate, -xOffset, -yOffset );
// 发送非客户区绘制消息
WinMsg_Send( hWnd, WM_NCPAINT, (WPARAM)hrgnUpdate, 0 );
//恢复
WinRgn_Offset( hrgnUpdate, xOffset, yOffset );
//得到非客户区区域
hrgnNC = _GetNClientRegion( lpws );
//去掉非客户区区域
WinRgn_Combine( hrgnUpdate, hrgnUpdate, hrgnNC, RGN_DIFF );
WinGdi_DeleteObject( hrgnNC );
}
}
else
{
}
//得到客户区矩形(窗口坐标)
rc = lpws->rectClient;
//转换到屏幕坐标
OffsetRect( &rc, lpws->rectWindow.left, lpws->rectWindow.top );
lpPaint->hdc = GetPaintDC( hWnd, &rc, hrgnUpdate, flags | DCF_BEGIN_PAINT_ALLOC );
WinRgn_GetBox( hrgnUpdate, &lpPaint->rcPaint );
//转换到客户区坐标
OffsetRect( &lpPaint->rcPaint, -(lpws->rectWindow.left+lpws->rectClient.left), -(lpws->rectWindow.top+lpws->rectClient.top) );
#ifdef EML_DOS
_HideMouse();
#endif
//假如可能,隐藏caret
if( lpPaint->hdc )
_HideCaret( hWnd, lpPaint->hdc );
//擦除背景
lpPaint->fErase = (BOOL)WinMsg_Send( hWnd, WM_ERASEBKGND, (WPARAM)lpPaint->hdc, 0 );
return lpPaint->hdc;
}
return NULL;
}
// **************************************************
// 声明:int WINAPI WinGdi_ReleaseDC( HWND hWnd, HDC hdc )
// 参数:
// IN hWnd-窗口句柄
// IN hdc-DC句柄
// 返回值:
// 成功:返回1
// 否则:返回0
// 功能描述:
// 释放DC
// 引用:
// 系统API
// ************************************************
int WINAPI WinGdi_ReleaseDC( HWND hWnd, HDC hdc )
{
#ifdef EML_DOS
_ShowMouse();
#endif
return ReleasePaintDC( hWnd, hdc );
}
// **************************************************
// 声明:BOOL WINAPI WinGdi_EndPaint( HWND hWnd, const PAINTSTRUCT *lpPaint )
// 参数:
// IN hWnd-窗口句柄
// IN lpPaint- PAINTSTRUCT结构指针
// 返回值:
// 假如成功,返回TRUE;否则,返回FALSE
// 功能描述:
// 结束并释放DC
// 引用:
// 系统API
// ************************************************
#define DEBUG_WinGdi_EndPaint 0
BOOL WINAPI WinGdi_EndPaint( HWND hWnd, const PAINTSTRUCT *lpPaint )
{
if( lpPaint->hdc )
{
_ShowCaret( hWnd, lpPaint->hdc );
WinGdi_ReleaseDC( hWnd, lpPaint->hdc );
}
else
{
ASSERT( 0 );
ERRORMSG( DEBUG_WinGdi_EndPaint, ( "error in WinGdi_EndPaint: invalid hdc.\r\n" ) );
}
return TRUE;
}
// **************************************************
// 声明:BOOL WINAPI Win_BringToTop( HWND hWnd )
// 参数:
// IN hWnd – 窗口句柄
// 返回值:
// 假如成功,返回TRUE;否则,返回FALSE
// 功能描述:
// 将窗口放到Z序的顶层
// 引用:
// 系统API
// ************************************************
BOOL WINAPI Win_BringToTop( HWND hWnd )
{
return Win_SetPos( hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE );
}
// **************************************************
// 声明:LRESULT WINAPI Win_CallProc( WNDPROC lpPrevWndFunc, HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam )
// 参数:
// IN lpPrevWndFunc – 前一个窗口消息处理函数
// IN hWnd – 窗口句柄
// IN msg – 窗口消息
// IN wParam – 第一个参数
// IN lParam – 第二个参数
// 返回值:
// 依赖于具体的消息
// 功能描述:
// 回调窗口消息处理函数
// 引用:
// 系统API
// ************************************************
LRESULT WINAPI Win_CallProc( WNDPROC lpPrevWndFunc, HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam )
{
_LPWINDATA lpws;
lpws = _GetHWNDPtr( hWnd );
if( lpws )
{
if( (DWORD)lpPrevWndFunc == -1 )
lpPrevWndFunc = lpws->lpClass->wc.lpfnWndProc; // 用类默认的消息处理函数
return _CallWindowProc( lpws, lpPrevWndFunc, Msg, wParam, lParam );
}
return -1;
}
// **************************************************
// 声明:HWND WINAPI Win_ChildFromPoint( HWND hParent, int x, int y, UINT uFlags )
// 参数:
// IN hParent - 父窗口
// IN x - x 坐标(客户坐标)
// IN y - y 坐标(客户坐标)
// IN uFlags - 附加标志
// 返回值:
// 假如成功,返回拥有该点的子窗口;否则,返回NULL
// 功能描述:
// 得到拥有该点的子窗口
// 引用:
// 系统API
// ************************************************
HWND WINAPI Win_ChildFromPoint( HWND hParent, int x, int y, UINT uFlags )
{
_LPWINDATA lpwsParent = _GetHWNDPtr( hParent );
HWND hwndHas = 0;
POINT point;
point.x = x;
point.y = y;
ASSERT( lpwsParent );
if( lpwsParent )
{ //父窗口有效
_LPWINDATA lpwsChild = lpwsParent->lpwsChild;
//将点转化到屏幕坐标
Win_ClientToScreen( hParent, &point );
//
if( PtInRect( &lpwsParent->rectWindow, point ) )
{ // 点在父窗口内 search all child windows
hwndHas = hParent;
//搜索所有的子窗口,检查是否拥有该点
while( lpwsChild )
{
if( uFlags == CWP_ALL )
{ //搜索所有的子窗口
if( PtInRect( &lpwsChild->rectWindow, point ) )
{ //在该子窗口
hwndHas = lpwsChild->hThis;
break;
}
}
else
{ //仅仅搜索的有效的子窗口
if( (uFlags & CWP_SKIPINVISIBLE) &&
IS_SHOWENABLE( lpwsChild->dwMainStyle ) == 0 //为 ShowDesktop修改
)
goto CFP_NEXTWIN;
if( (uFlags & CWP_SKIPDISABLED) &&
(lpwsChild->dwMainStyle & WS_DISABLED ) )
goto CFP_NEXTWIN;
if( PtInRect( &lpwsChild->rectWindow, point ) )
{ //命中
hwndHas = lpwsChild->hThis;
break;
}
}
CFP_NEXTWIN:
//下一个
lpwsChild = lpwsChild->lpwsNext;
}
}
}
return hwndHas;
}
// **************************************************
// 声明:BOOL WINAPI Win_ClientToScreen( HWND hWnd, LPPOINT lpPoint )
// 参数:
// IN hWnd--窗口句柄
// IN lpPoint--客户坐标,当成功返回时,将用来保存屏幕坐标
// 返回值:
// 假如成功,返回TRUE;否则,返回FALSE
// 功能描述:
// 客户坐标到屏幕坐标
// 引用:
// 系统API
// ************************************************
BOOL WINAPI Win_ClientToScreen( HWND hWnd, LPPOINT lpPoint )
{
_LPWINDATA lpws = _GetHWNDPtr( hWnd );
if( lpws )
{
lpPoint->x += lpws->rectClient.left + lpws->rectWindow.left;
lpPoint->y += lpws->rectClient.top + lpws->rectWindow.top;
return TRUE;
}
return FALSE;
}
// **************************************************
// 声明:BOOL WINAPI Win_Close( HWND hWnd )
// 参数:
// IN hWnd--窗口句柄
// 返回值:
// 假如成功,返回TRUE;否则,返回FALSE
// 功能描述:
// 关闭窗口
// 引用:
// 系统API
// ************************************************
BOOL WINAPI Win_Close( HWND hWnd )
{ // minimize the window
//Win_Show( hWnd, SW_MINIMIZE );
return TRUE;
}
// **************************************************
// 声明:HWND WINAPI Win_CreateEx(
// DWORD dwExStyle,
// LPCBYTE lpClassName,
// LPCBYTE lpText,
// DWORD dwMainStyle,
// int x, int y, int dx, int dy,
// HWND hParent,
// HMENU hMenu,
// HINSTANCE hInstance,
// LPVOID lpCreateParams )
// 参数:
// IN dwExStyle-扩展风格,包含:
// WS_EX_TOPMOST-顶层窗口
// IN lpClassName-类名
// IN lpText-标题
// IN dwMainStyle-风格
// WS_OVERLAPPED-可重叠式
// WS_POPUP-弹出式
// WS_CHILD-子窗口
// WS_CLIPSIBLINGS-裁剪兄弟窗口
// WS_CLIPCHILDREN-裁剪子窗口
// WS_CAPTION-有标题
// WS_BORDER-有单边框
// WS_DLGFRAME-对话框边框
// WS_VSCROLL-垂直滚动条
// WS_HSCROLL-水平滚动条
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -