分享
 
 
 

实现窗体自动隐藏(c代码)

王朝vc·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

实现窗体自动隐藏(c代码)

最近写个小程序,想让窗体自动隐藏,到csdn搜索,发现不少网友问这个问题,可是具体实现的例子不多,我经过琢磨,实现可记录停靠位置,可左上右三方停靠并隐藏。现将实现的例子拿出来供大家参考。

实现窗体自动隐藏方法有多种,可以使用定时器,不断监视鼠标,当鼠标移动到窗体边缘时,显示窗体,当鼠标离开后隐藏窗体。也可以在鼠标收到WM_NCMOUSEMOVE或 WM_MOUSEMOVE(无边框窗体)时激活窗体,然后在窗体消息WM_ACTIVE中设置显示或隐藏,这种方法在窗体未失去焦点时不会隐藏。我在原本的设计中便使用这种方法,只是在设计时发现非主窗体不太合适,激活窗体时会出现两个键盘焦点,而且我所需要的焦点是虚假的,可能我的设计不当,那位朋友若能完美实现,不妨交流一下。

本代码的流程如下:

1. 初始化窗体时设置窗体位置,并设置依靠状态窗体状态。

2. 当接收到WM_MOUSEMOVE消息时,检查窗体是否显示,若否,显示,并打开定时器。

3. 在WM_MOVING中检测窗体位置,并自动靠拢边界。

4. 在定时器中检测鼠标,当鼠标离开窗体后,关闭定时器,隐藏窗体。

当然,在隐藏窗体时首先判断位置,若停靠在边缘,则隐藏,否则,不隐藏。

现在我们一步步看代码。

int alignType; //全局变量,用于记录窗体停靠状态

enum

{

ALIGN_NONE, //不停靠

ALIGN_TOP, //停靠上边

ALIGN_LEFT, //停靠左边

ALIGN_RIGHT //停靠右边

};

#define NEAR_SIZE 20 //定义自动停靠有效距离

#define NEAR_SIDE 2 //窗体隐藏后在屏幕上保留的像素,以使鼠标可以触及

/*

下面代码处理窗体消息WM_MOVING,pRect是由参数lParam传来的指针

*/

void OnMoving(HWND hWnd, LPRECT pRect)

{

//未靠边界由pRect测试

if (alignType == ALIGN_NONE)

{

if (pRect->top < NEAR_SIZE) //在上边有效距离内,自动靠拢。

{

alignType = ALIGN_TOP;

pRect->bottom -= pRect->top;

pRect->top = 0;

}

if (pRect->left < NEAR_SIZE) //在左边有效距离内

{

alignType = ALIGN_LEFT;

pRect->right -= pRect->left;

pRect->left = 0;

}

else if (pRect->right + NEAR_SIZE > ScreenX) //在右边有效距离内,ScreenX为屏幕宽度,可由GetSystemMetrics(SM_CYSCREEN)得到。

{

alignType = ALIGN_RIGHT;

pRect->left += (ScreenX - pRect->right);

pRect->right = ScreenX;

}

}

else

{

//靠边界由鼠标测试

POINT pt;

GetCursorPos(&pt);

if (alignType == ALIGN_TOP)

{

if (pt.y > NEAR_SIZE) //由于我们移动窗体时,鼠标在标题栏内,当鼠标位置超过有效距离后,我们可以考虑用户要向下拖动鼠标。我们便解除上部停靠。

{

alignType = ALIGN_NONE;

pRect->bottom += NEAR_SIZE;

pRect->top = NEAR_SIZE;

}

else

{

pRect->bottom -= pRect->top;

pRect->top = 0;

if (pRect->left < NEAR_SIZE) //在上部停靠时,我们也考虑左右边角。

{

pRect->right -= pRect->left;

pRect->left = 0;

}

else if (pRect->right + NEAR_SIZE > ScreenX)

{

pRect->left += (ScreenX - pRect->right);

pRect->right = ScreenX;

}

}

}

if (alignType == ALIGN_LEFT)

{

if (pt.x - pRect->right > 0) //鼠标可以在整个标题条来回移动,所以我们不能简单用左边界和鼠标的距离来解除停靠,这里我们在鼠标离开右边界时解除停靠。

{

alignType = ALIGN_NONE;

pRect->right += NEAR_SIZE;

pRect->left = NEAR_SIZE;

}

else

{

pRect->right -= pRect->left;

pRect->left = 0;

if (pRect->top < NEAR_SIZE) //考虑左上角。

{

pRect->bottom -= pRect->top;

pRect->top = 0;

}

}

}

else if (alignType == ALIGN_RIGHT)

{

if (pt.x < pRect->left) //当鼠标离开左边界时,解除停靠。

{

alignType = ALIGN_NONE;

pRect->left -= NEAR_SIZE;

pRect->right -= NEAR_SIZE;

}

else

{

pRect->left += (ScreenX - pRect->right);

pRect->right = ScreenX;

if (pRect->top < NEAR_SIZE) //考虑右上角。

{

pRect->bottom -= pRect->top;

pRect->top = 0;

}

}

}

}

}

/*

在窗体初始化是设定窗体状态,如果可以停靠,便停靠在边缘

我本想寻求其他方法来解决初始化,而不是为它专一寻求一个函数,可是,窗体初始化时不发送WM_MOVING消息,我不得不重复类似任务.

*/

void NearSide(HWND hWnd)

{

int change = 0;

RECT rect;

GetWindowRect(hWnd, &rect);

alignType = ALIGN_NONE;

if (rect.left < NEAR_SIZE)

{

alignType = ALIGN_LEFT;

if ((rect.left != 0) && rect.right != NEAR_SIDE)

{

rect.right -= rect.left;

rect.left = 0;

change = 1;

}

}

else if (rect.right > ScreenX - NEAR_SIZE)

{

alignType = ALIGN_RIGHT;

if (rect.right != ScreenX && rect.left != ScreenX - NEAR_SIDE)

{

rect.left += (ScreenX - rect.right);

rect.right = ScreenX;

change = 1;

}

}

//调整上

else if (rect.top < NEAR_SIZE)

{

alignType = ALIGN_TOP;

if (rect.top != 0 && rect.bottom != NEAR_SIDE)

{

rect.bottom -= rect.top;

rect.top = 0;

change = 1;

}

}

if (change)

{

MoveWindow(hWnd, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, TRUE);

}

}

/*

窗体的显示隐藏由该函数完成,参数hide决定显示还是隐藏.

*/

void HideSide(HWND hWnd, BOOL hide)

{

RECT rc;

int moves = 20; //动画滚动窗体的步数,如果你觉得不够平滑,可以增大该值.

int xStep, yStep;

int xEnd, yEnd;

int width;

int height;

register int i;

GetWindowRect(hWnd, &rc);

width = rc.right - rc.left;

height = rc.bottom - rc.top;

//下边判断窗体该如何移动,由停靠方式决定

switch (alignType)

{

case ALIGN_TOP:

{

//向上移藏

xStep = 0;

xEnd = rc.left;

if (hide)

{

yStep = -rc.bottom / moves;

yEnd = -height + NEAR_SIDE;

}

else

{

yStep = -rc.top / moves;

yEnd = 0;

}

break;

}

case ALIGN_LEFT:

{

//向左移藏

yStep = 0;

yEnd = rc.top;

if (hide)

{

xStep = -rc.right / moves;

xEnd = -width + NEAR_SIDE;

}

else

{

xStep = -rc.left / moves;

xEnd = 0;

}

break;

}

case ALIGN_RIGHT:

{

//向右移藏

yStep = 0;

yEnd = rc.top;

if (hide)

{

xStep = (ScreenX - rc.left) / moves;

xEnd = ScreenX - NEAR_SIDE;

}

else

{

xStep = (ScreenX - rc.right) / moves;

xEnd = ScreenX - width;

}

break;

}

default:

return;

}

//动画滚动窗体.

for (i = 0; i < moves; i++)

{

rc.left += xStep;

rc.top += yStep;

SetWindowPos(hWnd, NULL, rc.left, rc.top, 0, 0, SWP_NOSIZE | SWP_NOSENDCHANGING);

RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);

Sleep(5);

}

SetWindowPos(hWnd, NULL, xEnd, yEnd, 0, 0, SWP_NOSIZE);

if (!hide) //如果窗体已被显示,设置定时器.监视鼠标.

{

SetTimer(hWnd, WM_TIMER, 500, NULL);

}

}

//下面就是通过窗体回调函数将这些函数组织起来.

//这里仅列出使用的消息

case WM_TIMER: //定时器消息

{

POINT pt;

RECT rc;

GetCursorPos(&pt);

GetWindowRect(hWnd, &rc);

if (!PtInRect(&rc, pt)) //若鼠标不在窗体内,隐藏窗体.

{

KillTimer(hWnd, WM_TIMER);

HideSide(hWnd, TRUE);

}

break;

}

case WM_CREATE:

case WM_INITDIALOG: //初始化消息

{

SetWindowPos(...) //程序保存窗体上次靠位置,在这里恢复.

NearSide(hWnd);

break;

}

//这两个消息是在窗体移动开始时和结束时产生的,我们在窗体开始移动时关闭定时器,移动结束后再打开,这样避免窗体移动时隐藏,金山快译的浮动条就有这种情况出现.

case WM_ENTERSIZEMOVE:

{

KillTimer(hWnd, WM_TIMER);

break;

}

case WM_EXITSIZEMOVE:

{

SetTimer(hWnd, WM_TIMER, 500, NULL);

break;

}

case WM_MOUSEMOVE: //受到窗体移动消息时,判断窗体是否显示,

{

RECT rc;

GetWindowRect(hWnd, &rc);

if (rc.left < 0 || rc.top < 0 || rc.right > ScreenX) //未显示

HideSide(hWnd, FALSE);

break;

}

case WM_MOVING: //处理窗体移动时消息,实现自动停靠

{

OnMoving(hWnd, (LPRECT) lParam);

break;

}

case WM_MOVE:

{

//保存窗体位置

}

这些代码是从我的程序中摘录出来的, 我已尽量检查它们的完整性, 但人总有犯错的时候, 如果你发现这些代码有问题, 或有更好的建议, 请联系我, 我的E-Mail:ggg82@sina.com

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有