主题:【原创】SDK方式实现窗口分隔条效果
窗口分隔条(Splitter)在MFC中有现成的类CSplitterWnd可以使用,并且VC安装目录SRC文件夹下的WINSPLIT.CPP文件有相应的源代码可以参考。使用SDK方式实现的网上也有不少的实例代码,我所搜索到的文章均需建立另外一个窗口,然后以这个窗口为媒介移动其余窗口。使用VC工具Spy++查看使用CSplitterWnd的MFC程序,发现好像没有这么一个第三方窗口,“窗口”效果只是视觉上的。本文将用SDK方式实现这种虚拟的分割条效果(水平分割)。
一般的分隔条具有以下特征:1、在分割条位置鼠标光标变为东西向的移动光标;2、在分割条位置按下鼠标左键显示分割条,保持左键按下移动鼠标,滚动条随鼠标移动,放开鼠标,分隔条消失,窗口位置做相应的调整;3、窗口消息改变时,左右子窗口填满整个客户区。
根据以上三条特征编写代码如下:
///////////////////////////////////////代码开始//////////////////////////////////////////////
/*
资源文件仅有一对话框(ID为IDD_DIALOG1),对话框中为一个树状控件(ID为IDC_TREEVIEW)和一个列表控件(ID为IDC_LISTVIEW)
原文地址:http://zlhex.blog.163.com/blog/static/1827743420112218459536/
*/
#include <windows.h>
#include "resource.h"
#pragma comment(linker,"/ENTRY:EntryPoint")
INT_PTR CALLBACK MainDialogProc(HWND,UINT,WPARAM,LPARAM);
void EntryPoint()
{
HINSTANCE hInstance;
hInstance = GetModuleHandle(NULL);
DialogBoxParam(hInstance,MAKEINTRESOURCE(IDD_DIALOG1),NULL,MainDialogProc,(LPARAM)NULL);
ExitProcess(0);
}
INT_PTR CALLBACK MainDialogProc(HWND hDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
static int cxClient,cyClient,xPos=300,flag;
static HWND hTreeView,hListView;
static HCURSOR hSizeWE;
static HDC hdc;
POINT pt;
RECT rc;
switch(uMsg)
{
case WM_SETCURSOR:
if(LOWORD(lParam)==HTCLIENT)
{
GetCursorPos(&pt);
ScreenToClient(hDlg,&pt);
if(pt.x>=xPos-2&&pt.x<=xPos+2)//4个像素范围
{
flag = 1;
SetCursor(hSizeWE);
return 1;
}
flag = 0;
}
break;
case WM_MOUSEMOVE:
if(flag==2)
{
Rectangle(hdc,xPos-3,0,xPos+3,cyClient);
xPos = (int)LOWORD(lParam);
Rectangle(hdc,xPos-3,0,xPos+3,cyClient);
}
return TRUE;
case WM_LBUTTONDOWN:
if(flag==1)
{
flag = 2;
Rectangle(hdc,xPos-3,0,xPos+3,cyClient);
GetClientRect(hDlg,&rc);
MapWindowPoints(hDlg,NULL,(LPPOINT)&rc,2);
ClipCursor(&rc);
SetCapture(hDlg);
}
return TRUE;
case WM_LBUTTONUP:
flag = 0;
Rectangle(hdc,xPos-3,0,xPos+3,cyClient);
SetWindowPos(hTreeView,0,0,0,xPos-2,cyClient,SWP_NOMOVE|SWP_NOZORDER);
SetWindowPos(hListView,0,xPos+2,0,cxClient-xPos-2,cyClient,SWP_NOZORDER);
ClipCursor(NULL);
ReleaseCapture();
return TRUE;
case WM_SIZE:
cxClient = LOWORD(lParam);
cyClient = HIWORD(lParam);
SetWindowPos(hTreeView,0,0,0,xPos-2,cyClient,SWP_NOMOVE|SWP_NOZORDER);
SetWindowPos(hListView,0,xPos+2,0,cxClient-xPos-2,cyClient,SWP_NOZORDER);
return 0;
case WM_INITDIALOG:
hTreeView = GetDlgItem(hDlg,IDC_TREEVIEW);
hListView = GetDlgItem(hDlg,IDC_LISTVIEW);
hSizeWE = LoadCursor(NULL,IDC_SIZEWE);
hdc = GetDC(hDlg);
SetROP2(hdc,R2_NOTXORPEN);
SelectObject(hdc,GetStockObject(GRAY_BRUSH));
return TRUE;
case WM_CLOSE:
ReleaseDC(hDlg,hdc);
EndDialog(hDlg,TRUE);
return TRUE;
}
return FALSE;
}
///////////////////////////////////////代码结束//////////////////////////////////////////////
程序运行效果见附件。
一般的分隔条具有以下特征:1、在分割条位置鼠标光标变为东西向的移动光标;2、在分割条位置按下鼠标左键显示分割条,保持左键按下移动鼠标,滚动条随鼠标移动,放开鼠标,分隔条消失,窗口位置做相应的调整;3、窗口消息改变时,左右子窗口填满整个客户区。
根据以上三条特征编写代码如下:
///////////////////////////////////////代码开始//////////////////////////////////////////////
/*
资源文件仅有一对话框(ID为IDD_DIALOG1),对话框中为一个树状控件(ID为IDC_TREEVIEW)和一个列表控件(ID为IDC_LISTVIEW)
原文地址:http://zlhex.blog.163.com/blog/static/1827743420112218459536/
*/
#include <windows.h>
#include "resource.h"
#pragma comment(linker,"/ENTRY:EntryPoint")
INT_PTR CALLBACK MainDialogProc(HWND,UINT,WPARAM,LPARAM);
void EntryPoint()
{
HINSTANCE hInstance;
hInstance = GetModuleHandle(NULL);
DialogBoxParam(hInstance,MAKEINTRESOURCE(IDD_DIALOG1),NULL,MainDialogProc,(LPARAM)NULL);
ExitProcess(0);
}
INT_PTR CALLBACK MainDialogProc(HWND hDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
static int cxClient,cyClient,xPos=300,flag;
static HWND hTreeView,hListView;
static HCURSOR hSizeWE;
static HDC hdc;
POINT pt;
RECT rc;
switch(uMsg)
{
case WM_SETCURSOR:
if(LOWORD(lParam)==HTCLIENT)
{
GetCursorPos(&pt);
ScreenToClient(hDlg,&pt);
if(pt.x>=xPos-2&&pt.x<=xPos+2)//4个像素范围
{
flag = 1;
SetCursor(hSizeWE);
return 1;
}
flag = 0;
}
break;
case WM_MOUSEMOVE:
if(flag==2)
{
Rectangle(hdc,xPos-3,0,xPos+3,cyClient);
xPos = (int)LOWORD(lParam);
Rectangle(hdc,xPos-3,0,xPos+3,cyClient);
}
return TRUE;
case WM_LBUTTONDOWN:
if(flag==1)
{
flag = 2;
Rectangle(hdc,xPos-3,0,xPos+3,cyClient);
GetClientRect(hDlg,&rc);
MapWindowPoints(hDlg,NULL,(LPPOINT)&rc,2);
ClipCursor(&rc);
SetCapture(hDlg);
}
return TRUE;
case WM_LBUTTONUP:
flag = 0;
Rectangle(hdc,xPos-3,0,xPos+3,cyClient);
SetWindowPos(hTreeView,0,0,0,xPos-2,cyClient,SWP_NOMOVE|SWP_NOZORDER);
SetWindowPos(hListView,0,xPos+2,0,cxClient-xPos-2,cyClient,SWP_NOZORDER);
ClipCursor(NULL);
ReleaseCapture();
return TRUE;
case WM_SIZE:
cxClient = LOWORD(lParam);
cyClient = HIWORD(lParam);
SetWindowPos(hTreeView,0,0,0,xPos-2,cyClient,SWP_NOMOVE|SWP_NOZORDER);
SetWindowPos(hListView,0,xPos+2,0,cxClient-xPos-2,cyClient,SWP_NOZORDER);
return 0;
case WM_INITDIALOG:
hTreeView = GetDlgItem(hDlg,IDC_TREEVIEW);
hListView = GetDlgItem(hDlg,IDC_LISTVIEW);
hSizeWE = LoadCursor(NULL,IDC_SIZEWE);
hdc = GetDC(hDlg);
SetROP2(hdc,R2_NOTXORPEN);
SelectObject(hdc,GetStockObject(GRAY_BRUSH));
return TRUE;
case WM_CLOSE:
ReleaseDC(hDlg,hdc);
EndDialog(hDlg,TRUE);
return TRUE;
}
return FALSE;
}
///////////////////////////////////////代码结束//////////////////////////////////////////////
程序运行效果见附件。