类似splitter的方式改变边窗大小
原来边窗style用了WS_THICKFRAME类型直接更改尺寸,有两个问题:
1.窗口大小连续更改,导致整个界面上的子窗口都连续调整大小和刷新,界面闪烁。
2.边窗另外的几条非移动边也可以拉动。
改为鼠标事件中对框架窗口局部区域的保存和绘制,移动过程中不造成界面重排,鼠标键抬起消息中结束,并将位置传给框架进行重排。
3.在绘制中用框架的设备句柄,鼠标的位置坐标从屏幕转换到框架比较容易,如果从边窗获取鼠标坐标,在其他非边窗位置绘制时转换比较晕。
效果如下图:
主要的程序:
PButtom.h
#pragma once #include "xwnd.h" #include "MsgBox.h" #include "StrBox.h" class CPBottom : public CXWnd { public: CPBottom(void); ~CPBottom(void); XDECLARE_DYNCREATE(CPBottom) public: HWND m_hTab; HWND CreateTab (HWND hWndParent); CMsgBox* m_pMsg; CStrBox* m_pStrBox; CXWnd* m_pMain; HWND m_hMainFrame; HWND m_hMainClient; virtual BOOL PreCreateWindow(WNDCLASSEX &cs); virtual int OnDestroy(HWND, UINT, WPARAM, LPARAM); int OnCreate(HWND, UINT, WPARAM, LPARAM); int OnSize(HWND, UINT, WPARAM, LPARAM); int OnClose(HWND, UINT, WPARAM, LPARAM); int OnNotify(HWND, UINT, WPARAM, LPARAM); int OnTimer(HWND, UINT, WPARAM, LPARAM); int OnLBDown(HWND, UINT, WPARAM, LPARAM); int OnLBUp(HWND, UINT, WPARAM, LPARAM); int OnMouseMove(HWND, UINT, WPARAM, LPARAM); HDC m_hdc_mem; HBITMAP m_hBitmap_mem; int m_xPos, m_yPos; int m_LBDown; XDECLARE_MESSAGE_MAP() };
PButtom.cpp
#include "StdAfx.h" #include "PBottom.h" #include "stdio.h" #include "Main.h" XIMPLEMENT_DYNCREATE(CPBottom, CXWnd) XBEGIN_MESSAGE_MAP(CPBottom, CXWnd) XON_MESSAGE(WM_CREATE, OnCreate) XON_MESSAGE(WM_SIZE, OnSize) XON_MESSAGE(WM_CLOSE, OnClose) XON_MESSAGE(WM_NOTIFY, OnNotify) XON_MESSAGE(WM_TIMER, OnTimer) XON_MESSAGE(WM_LBUTTONDOWN, OnLBDown) XON_MESSAGE(WM_LBUTTONUP, OnLBUp) XON_MESSAGE(WM_MOUSEMOVE, OnMouseMove) XEND_MESSAGE_MAP() CPBottom::CPBottom(void) { wcscpy_s(szWindowClass,_T("PBottom")); // The title bar text wcscpy_s(szTitle,_T("PBottom")); m_pMsg = NULL; m_LBDown =0; } CPBottom::~CPBottom(void) { delete m_pMsg; } HWND CPBottom::CreateTab (HWND hWndParent) { RECT rcClient; HWND hWndTab; TCITEM tie; int i; TCHAR achTemp[4][16]={_T("Tab1"),_T("Tab2"),_T("Tab3"),_T("Tab4")}; // Temporary buffer for strings. InitCommonControls(); GetClientRect(hWndParent, &rcClient); hWndTab = CreateWindow(WC_TABCONTROL, TEXT("TabTest"), WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE|TCS_BOTTOM, //TCS_BOTTOM 0, 0, 0,0, hWndParent, (HMENU)IDM_VIEW_Tab1, m_hInst, NULL); if (hWndTab == NULL) { return NULL; } HIMAGELIST hImageList; hImageList = ImageList_Create(16, 16, ILC_COLOR32 | ILC_MASK, 15, 15); //size 16x16 X15 for(unsigned int i = 0 ; i < 15; i++) { HICON hIcon = LoadIcon(m_hInst, MAKEINTRESOURCE(IDI_ICON1 + i)); ImageList_AddIcon(hImageList, hIcon); DestroyIcon(hIcon); } SendMessage(hWndTab, TCM_SETIMAGELIST, 0, (LPARAM)hImageList); tie.mask = TCIF_TEXT | TCIF_IMAGE; tie.iImage = -1; for (i = 0; i < 3; i++) { tie.pszText = achTemp[i]; if (TabCtrl_InsertItem(hWndTab, i, &tie) == -1) { DestroyWindow(hWndTab); return NULL; } } return hWndTab; } BOOL CPBottom::PreCreateWindow(WNDCLASSEX &cs) { return TRUE; } extern HWND hPRINT; int CPBottom::OnCreate(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { long style; style = GetWindowLong(hWnd,GWL_STYLE); style &= ~WS_THICKFRAME; SetWindowLong(hWnd, GWL_STYLE,style ); m_pMsg = new CMsgBox(); m_pMsg->m_pMainFrame = m_pMain; m_pStrBox = new CStrBox(); m_pStrBox->m_pMainFrame = m_pMain; m_hTab = CreateTab(hWnd); m_pMsg->Create(m_hInst, m_hTab); m_pStrBox->Create(m_hInst, m_hTab); hPRINT = m_pMsg->m_hWndEditMsg; TCITEM tie; tie.mask = TCIF_TEXT | TCIF_IMAGE; tie.iImage = 0; tie.pszText = _T("MSG"); tie.lParam = (LPARAM)m_pMsg->m_hWnd; TabCtrl_SetItem(m_hTab, 0, &tie); tie.iImage = 11; tie.pszText = _T("STR"); tie.lParam = (LPARAM)m_pStrBox->m_hWnd; TabCtrl_SetItem(m_hTab, 1, &tie); SetTimer(hWnd, 1, 1000, NULL); return 0; } int CPBottom::OnTimer(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { return 1; } int CPBottom::OnSize(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int cxClient,cyClient; cxClient = LOWORD (lParam); cyClient = HIWORD (lParam); MoveWindow(m_hTab, 0, 6, cxClient, cyClient-6, TRUE); RECT rt; GetClientRect(m_hTab, &rt); cxClient = rt.right - rt.left; cyClient = rt.bottom - rt.top; MoveWindow(m_pMsg->m_hWnd, 3, 0, cxClient, cyClient -27, TRUE); MoveWindow(m_pStrBox->m_hWnd, 3, 0, cxClient, cyClient -27, TRUE); return CXWnd::OnSize( hWnd, message, wParam, lParam); } int CPBottom::OnNotify(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { RECT rt; LPNMHDR lphr = (LPNMHDR)lParam; if (wParam ==IDM_VIEW_Tab1) { switch (lphr->code) { case TCN_SELCHANGE: PRINT(_T("\r\ntab Change")); int sel = TabCtrl_GetCurSel(m_hTab); switch(sel) { case 0: PRINT(_T("\r\nTab0")); ShowWindow(m_pMsg->m_hWnd, SW_SHOW); ShowWindow(m_pStrBox->m_hWnd, SW_HIDE); break; case 1: PRINT(_T("\r\nTab1")); ShowWindow(m_pMsg->m_hWnd, SW_HIDE); ShowWindow(m_pStrBox->m_hWnd, SW_SHOW); break; case 2: PRINT(_T("\r\nTab2")); ShowWindow(m_pMsg->m_hWnd, SW_HIDE); ShowWindow(m_pStrBox->m_hWnd, SW_HIDE); break; } break; } } return ::DefWindowProc(hWnd, message, wParam, lParam); } int CPBottom::OnClose(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { // SendMessage(hWnd, WM_SYSCOMMAND, SC_MINIMIZE, 0); return 0; } int CPBottom::OnDestroy(HWND, UINT, WPARAM, LPARAM) { m_hWnd = NULL; //closeall no OnClose, only OnDestroy, this is virtual return 1; } int CPBottom::OnLBDown(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { HWND hWndFrame; HDC hdc_Frame; RECT rt; POINT pt; int iWidth; hWndFrame = GetParent(hWnd); //frame GetWindowRect(hWnd, &rt); iWidth = rt.right - rt.left; SetCapture(hWnd); SetCursor(LoadCursor(NULL, IDC_SIZENS)); //need hdc_Frame = GetDC(hWndFrame); m_hBitmap_mem = CreateCompatibleBitmap(hdc_Frame, iWidth, 6); //allot the space app m_hdc_mem = CreateCompatibleDC(hdc_Frame); SelectObject(m_hdc_mem, m_hBitmap_mem); GetCursorPos(&pt); //Screen Position ScreenToClient(hWndFrame, &pt); // Frame Position m_yPos = pt.y; //save the Frame Positon GetClientRect(hWndFrame, &rt); BitBlt(m_hdc_mem,0,0,iWidth,6, hdc_Frame, rt.left, m_yPos -3, SRCCOPY); //save MoveToEx(hdc_Frame, rt.left, m_yPos-2,&pt); LineTo(hdc_Frame,iWidth,m_yPos-2); MoveToEx(hdc_Frame, rt.left, m_yPos,&pt); LineTo(hdc_Frame,iWidth,m_yPos); MoveToEx(hdc_Frame, rt.left, m_yPos+2,&pt); LineTo(hdc_Frame,iWidth,m_yPos+2); m_LBDown =1; ReleaseDC(hWndFrame, hdc_Frame); return 1; } int CPBottom::OnMouseMove(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { HWND hWndFrame; HDC hdc_Frame; RECT rt; POINT pt; int Mouse_y; int iWidth; hWndFrame = GetParent(hWnd); Mouse_y = HIWORD(lParam); //Plane Position if(Mouse_y < 6) // only top { SetCursor(LoadCursor(NULL, IDC_SIZENS)); } if(m_LBDown ==0) // no Click capture { return 0; } GetWindowRect(hWnd, &rt); iWidth = rt.right - rt.left; SetCapture(hWnd); hdc_Frame = GetDC(hWndFrame); //Frame DC GetClientRect(hWndFrame, &rt); BitBlt(hdc_Frame, rt.left, m_yPos - 3, iWidth, 6, m_hdc_mem, 0, 0, SRCCOPY); // restore yPos is old GetCursorPos(&pt); //Screen Position ScreenToClient(hWndFrame, &pt); // Frame Position m_yPos = pt.y; //save the Frame Positon GetClientRect(hWndFrame, &rt); BitBlt(m_hdc_mem, 0,0,iWidth,6, hdc_Frame,rt.left,m_yPos-3, SRCCOPY); //save Frame yPos is new MoveToEx(hdc_Frame, rt.left, m_yPos-2,&pt); //draw in frame LineTo(hdc_Frame, iWidth,m_yPos-2); MoveToEx(hdc_Frame, rt.left, m_yPos,&pt); LineTo(hdc_Frame,iWidth,m_yPos); MoveToEx(hdc_Frame, rt.left, m_yPos+2,&pt); LineTo(hdc_Frame,iWidth,m_yPos+2); ReleaseDC(hWndFrame,hdc_Frame); return 1; } int CPBottom::OnLBUp(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { HWND hWndFrame; HDC hdc_Frame; RECT rt; POINT pt; int Mouse_y; int iWidth; hWndFrame = GetParent(hWnd); //frame GetWindowRect(hWnd, &rt); iWidth = rt.right - rt.left; hdc_Frame = GetDC(hWndFrame); ReleaseCapture(); m_LBDown =0; GetClientRect(hWndFrame, &rt); BitBlt(hdc_Frame,rt.left,m_yPos-3,iWidth,6, m_hdc_mem,0,0, SRCCOPY); // restore yPos is old ReleaseDC(hWndFrame,hdc_Frame); DeleteDC(m_hdc_mem); DeleteObject(m_hBitmap_mem); SendMessage(hWndFrame,WM_COMMAND, IDM_WM_RESIZE, (LPARAM) m_yPos); return 1; }
也可以把这个操作单独做一个splitter的窗口类,就是框架排起来窗口要多出几个splitter窗。