当前位置导航:炫浪网>>网络学院>>编程开发>>C++教程>>C++进阶与实例

开发精彩实例:窗体自动隐藏

实现窗体自动隐藏方法有多种,可以使用定时器,不断监视鼠标,当鼠标移动到窗体边缘时,显示窗体,当鼠标离开后隐藏窗体。也可以在鼠标收到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;
    }
    }
 

共2页 首页 上一页 1 2 下一页 尾页 跳转到
相关内容
赞助商链接