类似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窗。

 

posted @ 2022-05-12 10:14  XGZ21  阅读(48)  评论(0编辑  收藏  举报