C#无框窗体的隐藏代码是啥?(类似QQ停靠桌面边缘自动隐藏)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C#无框窗体的隐藏代码是啥?(类似QQ停靠桌面边缘自动隐藏)相关的知识,希望对你有一定的参考价值。

说明具体事件的用法

工具箱里去找 noti。。开头的控件!
QQ的边缘弹下来这一步:当鼠标触及边缘后,界面整体下移到这个界面出现为止;当鼠标离开界面后,界面会上移出屏幕,就实现了“隐藏”就是利用移动他实现隐藏!
// TestDlg.cpp : implementation file
//
#include "stdafx.h"
#include "Test.h"
#include "TestDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

int ScreenX; //屏幕宽度
int ScreenY; //屏幕高度
int alignType; //全局变量,用于记录窗体停靠状态
enum

ALIGN_NONE, //不停靠
ALIGN_TOP, //停靠上边
ALIGN_LEFT, //停靠左边
ALIGN_RIGHT //停靠右边
;
#define NEAR_SIZE 5 //定义自动停靠有效距离
#define NEAR_SIDE 3 //窗体隐藏后在屏幕上保留的像素,以使鼠标可以触及
/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialog

public:
CAboutDlg();
// Dialog Data
//AFX_DATA(CAboutDlg)
enum IDD = IDD_ABOUTBOX ;
//AFX_DATA
// ClassWizard generated virtual function overrides
//AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//AFX_VIRTUAL
// Implementation
protected:
//AFX_MSG(CAboutDlg)
//AFX_MSG
DECLARE_MESSAGE_MAP()
;
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)

//AFX_DATA_INIT(CAboutDlg)
//AFX_DATA_INIT

void CAboutDlg::DoDataExchange(CDataExchange* pDX)

CDialog::DoDataExchange(pDX);
//AFX_DATA_MAP(CAboutDlg)
//AFX_DATA_MAP

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//AFX_MSG_MAP(CAboutDlg)
// No message handlers
//AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CTestDlg dialog
CTestDlg::CTestDlg(CWnd* pParent /*=NULL*/)
: CDialog(CTestDlg::IDD, pParent)

//AFX_DATA_INIT(CTestDlg)
// NOTE: the ClassWizard will add member initialization here
//AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

void CTestDlg::DoDataExchange(CDataExchange* pDX)

CDialog::DoDataExchange(pDX);
//AFX_DATA_MAP(CTestDlg)
// NOTE: the ClassWizard will add DDX and DDV calls here
//AFX_DATA_MAP

BEGIN_MESSAGE_MAP(CTestDlg, CDialog)
//AFX_MSG_MAP(CTestDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_WM_MOVING()
ON_WM_TIMER()
ON_WM_NCMOUSEMOVE()
//AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CTestDlg message handlers
BOOL CTestDlg::OnInitDialog()

CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)

CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())

pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);


// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon

// TODO: Add extra initialization here
ScreenX = GetSystemMetrics(SM_CXSCREEN);
ScreenY = GetSystemMetrics(SM_CYSCREEN);
SetTimer(WM_TIMER,50,NULL);
NearSide(GetSafeHwnd()); //如果位置合适让窗体自动隐藏
return TRUE; // return TRUE unless you set the focus to a control

void CTestDlg::OnSysCommand(UINT nID, LPARAM lParam)

if ((nID & 0xFFF0) == IDM_ABOUTBOX)

CAboutDlg dlgAbout;
dlgAbout.DoModal();

else
-
CDialog::OnSysCommand(nID, lParam);


// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CTestDlg::OnPaint()

if (IsIconic())

CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);

else

CDialog::OnPaint();


// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CTestDlg::OnQueryDragIcon()

return (HCURSOR) m_hIcon;

void CTestDlg::HideSide(HWND hWnd, BOOL hide)

RECT rc;
int moves = 2; //动画滚动窗体的步数,如果你觉得不够平滑,可以增大该值.
int xStep, yStep;
int xEnd, yEnd;
int width;
int height;
register int i;

GetWindowRect(&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(NULL, rc.left, rc.top, 0, 0,
SWP_NOSIZE | SWP_NOSENDCHANGING);
RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);

Sleep(5);


SetWindowPos(NULL, xEnd, yEnd, 0, 0, SWP_NOSIZE);
if (!hide) //如果窗体已被显示,设置定时器.监视鼠标.

SetTimer(WM_TIMER, 50, NULL);


void CTestDlg::NearSide(HWND hWnd)

int change = 0;
RECT rect;

GetWindowRect(&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;


//调整上下
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(rect.left, rect.top, rect.right - rect.left,
rect.bottom - rect.top, TRUE);


void CTestDlg::OnMoving(UINT fwSide, LPRECT pRect)

CDialog::OnMoving(fwSide, pRect);

// TODO: Add your message handler code here
//未靠边界由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);
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);
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;





void CTestDlg::OnTimer(UINT nIDEvent)

// TODO: Add your message handler code here and/or call default
POINT pt;
RECT rc;

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

//KillTimer(hWnd, WM_TIMER);
KillTimer(WM_TIMER);
//HideSide(hWnd, TRUE);
HideSide(GetSafeHwnd(),TRUE);

CDialog::OnTimer(nIDEvent);

void CTestDlg::OnNcMouseMove(UINT nHitTest, CPoint point)

// TODO: Add your message handler code here and/or call default
RECT rc;
GetWindowRect(&rc);
if (rc.left < 0 || rc.top < 0 || rc.right > ScreenX) //未显示

HideSide(GetSafeHwnd(), FALSE);
else

HideSide(GetSafeHwnd(), FALSE);
SetTimer(WM_TIMER,50,NULL);

CDialog::OnNcMouseMove(nHitTest, point);
参考技术A 停靠隐藏,自己做控件,或者去下载停靠隐藏控件,网上有 参考技术B 没做过,不过想来应该是响应Form 的 MouseEnter,MouseLeave 事件,改变Form状态。 参考技术C 正在学习C#,不清楚

C# winform 窗体左右一部分显示 一部分隐藏

就跟以前qq的那个什么代理一样,点一下显示出来。再点一下隐藏。新手麻烦稍微详细一点。谢谢

// 采用SplitContainer容器控件,可以实现QQ聊天窗口右侧边栏伸缩展开的效果。

if(splitContainer.Panel1Collapsed)

     splitContainer.Panel1Collapsed=false; // 展开
else

     splitContainer.Panel1Collapsed=true; // 收缩

参考技术A 在From窗体上,放2个panel控件,点击“隐藏”,将一个panel隐藏,将另一个panel显示,显示的那个panel重新设置它的大小追问

谢谢。我找到一个修改它大小的方法能用。 this.Width或者其他什么的来显示。

参考技术B Form1 frm = new Form1(); frm.Hide();窗体就隐藏

以上是关于C#无框窗体的隐藏代码是啥?(类似QQ停靠桌面边缘自动隐藏)的主要内容,如果未能解决你的问题,请参考以下文章

wpf里面类似 SplitterPanel SplitterItem 功能的控件怎么实现啊,可以拖放和停靠在窗体上

wpf仿qq边缘自动停靠,支持多屏

转 实现类似QQ的窗体停靠

wpf仿qq边缘自动停靠,支持多屏

C# winform是啥

窗体在屏幕边缘隐藏