⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tanchors.cpp

📁 mpq文件的格式就是一种压缩格式
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*****************************************************************************/
/* TAnchors.cpp                               Copyright Ladislav Zezula 2001 */
/*---------------------------------------------------------------------------*/
/* A class for easy object anchoring. Those who compare the Delphi program-  */
/* ming with Visual C++, will certainly miss the "Anchors" property in visual*/
/* design. This class supports something like that, although it's not so     */
/* comfort like the visual design in Delphi/C++ Builder                      */
/*---------------------------------------------------------------------------*/
/*   Date    Ver   Who  Comment                                              */
/* --------  ----  ---  -----------------------------------------------------*/
/* 19.12.01  1.00  Lad  Created                                              */
/* 21.12.01  1.01  Lad  Added TRACE outputs for debug support                */
/* 28.12.01  1.02  Lad  Added the __USE_FAST_REDRAW__ flag                   */
/* 09.01.01  1.02  Lad  Fixed ugly effect caused by the group boxes.         */
/* 15.07.03  1.03  Lad  Added method using DeferWindowPos                    */
/*****************************************************************************/

#include <tchar.h>
#include <windows.h>
#include <winuser.h>
#include <commctrl.h>

#include "TAnchors.h"

// Choose one flag only !!!
//#define __USE_SET_WINDOW_POS__        // Redraws the windows using SetWindowPos + WS_CLIPCHILDREN
#define __USE_DEFER_WINDOW_POS__        // Redraws windows using DeferWindowPos 
//#define __USE_FAST_REDRAW__           // Redraws windows using double buffering

//-----------------------------------------------------------------------------
// Constructor and destructor

TAnchors::TAnchors()
{
    // Initialize anchors to NULL
    m_pFirstAnchor = NULL;
}

TAnchors::~TAnchors()
{
    TAnchor * pAnchor = m_pFirstAnchor;
    TAnchor * temp;

    // Free all used anchors
    while(pAnchor != NULL)
    {
        temp = pAnchor->next;
        delete pAnchor;
        pAnchor = temp;
    }
}

//-----------------------------------------------------------------------------
// Public functions

// This function adds the anchors for an object into the list of anchors.
// Later when the window will be resized, the anchors will be applied.
BOOL TAnchors::AddAnchor(HWND hWnd, DWORD dwAnchors)
{
    TAnchor * newAnchor;
    TAnchor * lastAnchor = m_pFirstAnchor;
    HWND      hParent = GetParent(hWnd);// Parent of given window
    POINT     ptLT;                     // Left-top point in the client rectangle
    POINT     ptRB;                     // Right-bottom point in the client rectangle
    RECT      rect;                     // Window rect

    // Test if the window passed is valid
    if(IsWindow(hWnd) == FALSE || IsWindow(hParent) == FALSE)
    {
        OutputDebugString(_T("Invalid window handle passed to TAnchors::AddAnchor\n"));
        return FALSE;
    }

#ifdef __USE_SET_WINDOW_POS__
    // Add the WS_CLIPCHILDREN style to the parent. This fastens the window
    // redrawing. But I have found that the groupboxes make very ugly effect due to their
    // bad redrawing logic. So we must be careful and add the style only if no
    // groupbox was found inside the window.
    BOOL bFoundGroupBox = FALSE;
    for(HWND hChild = GetWindow(hParent, GW_CHILD); hChild != NULL; hChild = GetWindow(hChild, GW_HWNDNEXT))
    {
        char  szClassName[64];
        DWORD dwStyle = GetWindowLong(hChild, GWL_STYLE);

        // If we knew the group box, stop the searching (one group box is enough)
        GetClassNameA(hChild, szClassName, sizeof(szClassName));
        if(!stricmp(szClassName, "Button") && (dwStyle & BS_GROUPBOX))
        {
            bFoundGroupBox = TRUE;
            break;
        }
    }

    // Add the WS_CLIPCHILDREN style
    if(bFoundGroupBox == FALSE)
        SetWindowLong(hParent, GWL_STYLE, GetWindowLong(hParent, GWL_STYLE) | WS_CLIPCHILDREN);
#endif  // __USE_SET_WINDOW_POS__

    // Create the new anchor
    newAnchor = new TAnchor;
    ZeroMemory(newAnchor, sizeof(TAnchor));
    newAnchor->dwAnchors = dwAnchors;
    newAnchor->hWnd      = hWnd;

    // Retrieve the relative position of each window side
    GetClientRect(hParent, &newAnchor->parentRect);
    ptLT.x = newAnchor->parentRect.left;
    ptLT.y = newAnchor->parentRect.top;
    ptRB.x = newAnchor->parentRect.right;
    ptRB.y = newAnchor->parentRect.bottom;
    ClientToScreen(hParent, &ptLT);
    ClientToScreen(hParent, &ptRB);

    // Store the distances
    GetWindowRect(hWnd, &rect);
    newAnchor->left   = rect.left - ptLT.x;
    newAnchor->top    = rect.top  - ptLT.y;
    newAnchor->right  = ptRB.x - rect.right;
    newAnchor->bottom = ptRB.y - rect.bottom;
    newAnchor->width  = rect.right - rect.left;
    newAnchor->height = rect.bottom - rect.top;

    // Store the center relative distance
    newAnchor->dx = (double)(newAnchor->left + newAnchor->width / 2) / (double)newAnchor->parentRect.right;
    newAnchor->dy = (double)(newAnchor->top + newAnchor->height / 2) / (double)newAnchor->parentRect.bottom;

    // Insert anchor in the chain
    if(m_pFirstAnchor == NULL)
        m_pFirstAnchor = newAnchor;
    else
    {
        while(lastAnchor->next != NULL)
            lastAnchor = lastAnchor->next;

        lastAnchor->next = newAnchor;
    }
    return TRUE;
}

BOOL TAnchors::AddAnchor(HWND hParent, UINT ctrl, DWORD dwAnchors)
{
    return AddAnchor(GetDlgItem(hParent, ctrl), dwAnchors);
}

// This function makes the complete anchoring. It must be called in response to
// WM_SIZE message, or whenever the child windows need to be repositioned.
BOOL TAnchors::AnchorAllObjects(HWND hParent)
{
    TAnchor * pAnchor;
    RECT  NewRect;                      // New position and size of the resized window

    // If no anchored windows, or the parent is not a valid window, do nothing
    if(m_pFirstAnchor == NULL || IsWindow(hParent) == FALSE)
        return FALSE;

#ifdef __USE_SET_WINDOW_POS__
    for(pAnchor = m_pFirstAnchor; pAnchor != NULL; pAnchor = pAnchor->next)
    {
        if(GetNewWindowRect(hParent, pAnchor, NewRect)) 
        {
            SetWindowPos(pAnchor->hWnd, NULL, NewRect.left, NewRect.top, NewRect.right, NewRect.bottom, SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOOWNERZORDER);
            InvalidateRect(pAnchor->hWnd, NULL, TRUE);
        }
    }
#endif

// This method uses xxxDeferWindowPos and is the best one. Deferred window
// positioning is a part of Windows API and thus supported by Microsoft.
#ifdef __USE_DEFER_WINDOW_POS__
    HDWP  hDwp = NULL;
    int   nWindows = 0;

    // Count the anchored windows and begin the window positioning
    for(pAnchor = m_pFirstAnchor; pAnchor != NULL; pAnchor = pAnchor->next)
        nWindows++;
    hDwp = BeginDeferWindowPos(nWindows);
    for(pAnchor = m_pFirstAnchor; pAnchor != NULL; pAnchor = pAnchor->next)
    {
        if(GetNewWindowRect(hParent, pAnchor, NewRect)) 
            hDwp = DeferWindowPos(hDwp, pAnchor->hWnd, NULL, NewRect.left, NewRect.top, NewRect.right, NewRect.bottom, SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOOWNERZORDER);
    }
    EndDeferWindowPos(hDwp);
#endif

// This method is similar to using SetWindowPos, except that the redrawing
// is completely directed by us.
#ifdef __USE_FAST_REDRAW__
    SendMessage(hParent, WM_SETREDRAW, FALSE, 0);
    for(pAnchor = m_pFirstAnchor; pAnchor != NULL; pAnchor = pAnchor->next)
    {
        if(GetNewWindowRect(hParent, pAnchor, NewRect)) 
            SetWindowPos(pAnchor->hWnd, NULL, NewRect.left, NewRect.top, NewRect.right, NewRect.bottom, SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOOWNERZORDER);
    }

    // Fast redraw logic does not work properly in this moment
    // Problem : how to redraw the non-client area ?
    SendMessage(hParent, WM_SETREDRAW, TRUE, 0);
    PaintWindow(hParent, NULL);
#endif // __USE_FAST_REDRAW__

    return TRUE;
}

//-----------------------------------------------------------------------------
// This function calculates the new position of the window after the size
// of its parent has been changed.

BOOL TAnchors::GetNewWindowRect(HWND hParent, TAnchor * pAnchor, RECT & NewRect)
{
    POINT ptLT;
    RECT  winRect;                      // Screen rectangle of the moved window
    RECT  clientRect;                   // Client rectangle of the resized window
    int  x, y, cx, cy;                  // New window pos and size

    // Retrieve the client dimensions
    GetClientRect(hParent, &clientRect);
    ptLT.x = clientRect.left;
    ptLT.y = clientRect.top;
    ClientToScreen(hParent, &ptLT);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -