Как изменить высоту CHeaderCtrl (многострочную высоту)C++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Как изменить высоту CHeaderCtrl (многострочную высоту)

Сообщение Anonymous »

Я пытаюсь создать многострочный (двустрочный) заголовок — CHeaderCtrl из CListCtrl. Я не могу изменить высоту заголовка.
Как изменить высоту, не меняя шрифт?
Код двойной строки CHeaderCtrl:
файл «dlg.h»
#pragma once
#include "resource.h"
#include "framework.h"
#include
#include

using namespace std;

//My own header for multiline header
class CMyHeaderCtrl : public CHeaderCtrl
{
public:
DECLARE_MESSAGE_MAP()

void OnCustomDraw(NMHDR *pNMHDR, LRESULT *pResult);

void OnLButtonDown(UINT nFlags, CPoint point);
};

class CMFCtestDlg : public CDialogEx
{
// Construction
public:
CMFCtestDlg(CWnd *pParent = nullptr); // standard constructor
~CMFCtestDlg() { }

// Dialog Data
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_MFC_TEST_DIALOG };
#endif
protected:
map m_mapOfTab{{0,L"Nula"},{1,L"Jedna"},{2,L"Dva"}};

public:
CListCtrl m_cListCtrl; // First list control
CMyHeaderCtrl m_myHeaderCtrl;

protected:
virtual void DoDataExchange(CDataExchange *pDX); // DDX/DDV support

// Implementation
protected:
HICON m_hIcon;

// Generated message map functions
virtual BOOL OnInitDialog();
DECLARE_MESSAGE_MAP()
CMenu m_SplitMenu;
CMenu m_SplitSubMenu;

public:
void OnHeaderDropDown(NMHDR *pNMHDR, LRESULT *pResult);
};

Файл «dlg.cpp»
#include "pch.h"
#include "framework.h"
#include "MFC_test.h"
#include "MFC_testDlg.h"
#include "afxdialogex.h"

#include "resource.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

#define _MAJU_PRG_NAME L"Majklův řez"

// CMFCtestDlg dialog
CMFCtestDlg::CMFCtestDlg(CWnd *pParent /*=nullptr*/)
: CDialogEx(IDD_MFC_TEST_DIALOG, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
m_SplitMenu.LoadMenu(IDR_MENU);
}

void CMFCtestDlg::DoDataExchange(CDataExchange *pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_LIST, m_cListCtrl);

}

BEGIN_MESSAGE_MAP(CMFCtestDlg, CDialogEx)
ON_NOTIFY(HDN_DROPDOWN, IDC_LIST, &CMFCtestDlg::OnHeaderDropDown)
END_MESSAGE_MAP()

#define ID_MENU_ITEM1 35600
#define ID_MENU_ITEM2 35601

BOOL CMFCtestDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();

m_cListCtrl.InsertColumn(0, L"Column 1", LVCFMT_CENTER, 100);
m_cListCtrl.InsertColumn(1, L"FirstLine\nSecLin", LVCFMT_CENTER, 150);

CHeaderCtrl *pHeaderCtrl = m_cListCtrl.GetHeaderCtrl();
if(pHeaderCtrl)
{
m_myHeaderCtrl.SubclassWindow(pHeaderCtrl->GetSafeHwnd());

pHeaderCtrl->ModifyStyle(0, pHeaderCtrl->GetStyle() | HDS_BUTTONS);
// Modify the header item style to include the split button style
HDITEM item;
item.mask = HDI_FORMAT;
//item.iItem = 0; // Index of the header item you want to modify
pHeaderCtrl->GetItem(1, &item);
item.fmt |= HDF_SPLITBUTTON;

pHeaderCtrl->SetItem(1, &item);
RECT rect;
pHeaderCtrl->GetClientRect(&rect);
// rect.bottom += rect.bottom - rect.top; //Resize heigth of the Header to double heigth
rect.bottom += 50;
pHeaderCtrl->SetWindowPos(0, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, 0);
//double headerHeight = rect.bottom - rect.top;
}

CString csTxt;
map::const_iterator it = m_mapOfTab.begin();
for(int i = 0; it != m_mapOfTab.end(); ++it, ++i)
{
csTxt.Format(L"%i", it->first);
m_cListCtrl.InsertItem(i, csTxt.GetString());
m_cListCtrl.SetItemText(i, 1, it->second);
}

return TRUE;
}

void CMFCtestDlg::OnHeaderDropDown(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMHEADER phdr = reinterpret_cast(pNMHDR);

// Get the header control
CHeaderCtrl *pHeaderCtrl = m_cListCtrl.GetHeaderCtrl();

if(pHeaderCtrl != nullptr && phdr->iItem >= 0)
{
// Calculate the drop-down button rectangle
CRect rcItem;
pHeaderCtrl->GetItemRect(phdr->iItem, &rcItem);

// Get the position of the drop-down arrow button
CPoint point(rcItem.left, rcItem.bottom); // Show menu below the header item
pHeaderCtrl->ClientToScreen(&point); // Convert to screen coordinates

// Create and display the context menu

// Track the popup menu (display it at the arrow location)
m_SplitMenu.GetSubMenu(0)->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, this);
}
}

////////// CMyHeaderCtrl

BEGIN_MESSAGE_MAP(CMyHeaderCtrl, CHeaderCtrl)
ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, &CMyHeaderCtrl::OnCustomDraw)
ON_WM_LBUTTONDOWN()
ON_WM_PAINT()
END_MESSAGE_MAP()

void CMyHeaderCtrl::OnCustomDraw(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMCUSTOMDRAW pNMCD = reinterpret_cast(pNMHDR);

if(pNMCD->dwDrawStage == CDDS_PREPAINT)
{
*pResult = CDRF_NOTIFYITEMDRAW; // Request item draw notifications
}
else if(pNMCD->dwDrawStage == CDDS_ITEMPREPAINT)
{
*pResult = CDRF_SKIPDEFAULT; // Skip default drawing

// Set up the device context
CDC *pDC = CDC::FromHandle(pNMCD->hdc);
CRect rect = pNMCD->rc;
int itemIndex = static_cast(pNMCD->dwItemSpec);

// Set background color
pDC->FillSolidRect(&rect, RGB(240, 240, 240));

// Draw two lines of text
HDITEM hdItem;
TCHAR text[256];
hdItem.mask = HDI_TEXT;
hdItem.pszText = text;
hdItem.cchTextMax = sizeof(text) / sizeof(TCHAR);
GetItem(itemIndex, &hdItem);

CString headerText(hdItem.pszText);

// Split text by newline character "\n"
CString topText, bottomText;
AfxExtractSubString(topText, headerText, 0, '\n');
AfxExtractSubString(bottomText, headerText, 1, '\n');

// Calculate positions for two lines of text
rect.bottom += 5;
CRect rectTop = rect;
CRect rectBottom = rect;

rectTop.bottom = rect.top + rect.Height() / 2;
rectBottom.top = rectTop.bottom;

// Draw the first and second line of text
CHeaderCtrl *pHeaderCtrl = dynamic_cast(CWnd::FromHandle(pNMCD->hdr.hwndFrom));
HDITEM item;
item.mask = HDI_FORMAT;
pHeaderCtrl->GetItem(pNMCD->dwItemSpec, &item);
UINT uHdFormat = DT_LEFT;
if(item.fmt & LVCFMT_RIGHT)
uHdFormat = DT_RIGHT;
else if(item.fmt & LVCFMT_CENTER)
uHdFormat = DT_CENTER;

pDC->DrawText(topText, &rectTop, uHdFormat | DT_VCENTER | DT_SINGLELINE);
pDC->DrawText(bottomText, &rectBottom, uHdFormat | DT_VCENTER | DT_SINGLELINE);

if(item.fmt & HDF_SPLITBUTTON)
{
rect.left = rect.right - 16;
DrawFrameControl(pDC->m_hDC, &rect, DFC_SCROLL, DFCS_SCROLLDOWN);
}
}
}

//Split Button
#define ID_OPTION1 32500
#define ID_OPTION2 32501

void CMyHeaderCtrl::OnLButtonDown(UINT nFlags, CPoint point)
{
// Perform a hit-test to find the header item at the click position
HDHITTESTINFO hitTestInfo = {0};
hitTestInfo.pt = point;
int nItem = SendMessage(HDM_HITTEST, 0, (LPARAM) &hitTestInfo);

// Check if the click was on a split button
if(nItem >= 0 && (hitTestInfo.flags & HHT_ONHEADER))
{
HDITEM hdItem;
hdItem.mask = HDI_FORMAT;
if(GetItem(nItem, &hdItem) && (hdItem.fmt & HDF_SPLITBUTTON))
{
CRect itemRect;
if(!GetItemRect(nItem, &itemRect))
return CHeaderCtrl::OnLButtonDown(nFlags, point);

// Define an approximate width for the split button icon (e.g., 16 pixels)
const int iconWidth = 16;

// Calculate the area on the far right where the icon would be
CRect iconRect = itemRect;
iconRect.left = iconRect.right - iconWidth;

// Check if the click point falls within the icon area
if(iconRect.PtInRect(point))
{
// Show context menu or handle the split button click
CMenu menu;
menu.CreatePopupMenu();
menu.AppendMenu(MF_STRING, ID_OPTION1, _T("Option 1"));
menu.AppendMenu(MF_STRING, ID_OPTION2, _T("Option 2"));

ClientToScreen(&point);
menu.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, this);

return; // Stop further processing
}
}
}

// Call base class for default behavior if it wasn't a split button click
CHeaderCtrl::OnLButtonDown(nFlags, point);
}


Подробнее здесь: https://stackoverflow.com/questions/791 ... ine-height
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»