soui 5.0.0.1
Soui5 Doc
 
Loading...
Searching...
No Matches
SHeaderCtrl.cpp
1#include "souistd.h"
2#include "control/SHeaderCtrl.h"
3#include "helper/SDragWnd.h"
4
5SNSBEGIN
7 : m_bFixWidth(FALSE)
9 , m_bSortHeader(TRUE)
10 , m_pSkinItem(GETBUILTINSKIN(SKIN_SYS_HEADER))
11 , m_pSkinSort(NULL)
12 , m_dwHitTest((DWORD)-1)
13 , m_bDragging(FALSE)
14 , m_hDragImg(NULL)
15 , m_nScale(100)
16{
17 m_bClipClient = TRUE;
18 m_evtSet.addEvent(EVENTID(EventHeaderClick));
19 m_evtSet.addEvent(EVENTID(EventHeaderItemChanged));
20 m_evtSet.addEvent(EVENTID(EventHeaderItemChanging));
21 m_evtSet.addEvent(EVENTID(EventHeaderItemSwap));
22 m_evtSet.addEvent(EVENTID(EventHeaderRelayout));
23}
24
28
29int SHeaderCtrl::InsertItem(int iItem, LPCTSTR pszText, int nWidth, UINT fmt, LPARAM lParam, BOOL bDpiAware /*=FALSE*/, float fWeight /*=0.0f*/)
30{
31 SASSERT(pszText);
32 SASSERT(nWidth >= 0);
33 if (iItem == -1)
34 iItem = (int)m_arrItems.GetCount();
35 SHDITEMEX item;
36 item.mask = SHDI_ALL;
37 item.fmt = fmt;
38 item.fWeight = fWeight;
39 SLayoutSize szWid((float)nWidth, bDpiAware ? SLayoutSize::dp : SLayoutSize::px);
40 item.cx = szWid.toPixelSize(GetScale());
41 item.bDpiAware = bDpiAware;
42 item.strText.SetOwner(this);
43 item.strText.SetText(pszText, false);
44 item.state = 0;
45 item.iOrder = iItem;
46 item.lParam = lParam;
47 item.bVisible = TRUE;
48 m_arrItems.InsertAt(iItem, item);
49 //需要更新列的序号
50 for (size_t i = 0; i < GetItemCount(); i++)
51 {
52 if (i == (size_t)iItem)
53 continue;
54 if (m_arrItems[i].iOrder >= iItem)
55 m_arrItems[i].iOrder++;
56 }
57 EventHeaderRelayout e(this);
58 FireEvent(e);
59
60 Invalidate();
61 return iItem;
62}
63
64BOOL SHeaderCtrl::GetItem(int iItem, SHDITEM *pItem) const
65{
66 if ((UINT)iItem >= m_arrItems.GetCount())
67 return FALSE;
68 if (pItem->mask & SHDI_TEXT && pItem->pszText && pItem->cchMaxText)
69 {
70 _tcscpy_s(pItem->pszText, pItem->cchMaxText, m_arrItems[iItem].strText.GetText(FALSE).c_str());
71 }
72 if (pItem->mask & SHDI_WIDTH)
73 {
74 pItem->cx = GetItemWidth(iItem);
75 }
76 if (pItem->mask & SHDI_LPARAM)
77 pItem->lParam = m_arrItems[iItem].lParam;
78 if (pItem->mask & SHDI_FORMAT)
79 pItem->fmt = m_arrItems[iItem].fmt;
80 if (pItem->mask & SHDI_ORDER)
81 pItem->iOrder = m_arrItems[iItem].iOrder;
82 if (pItem->mask & SHDI_VISIBLE)
83 pItem->bVisible = m_arrItems[iItem].bVisible;
84 if (pItem->mask & SHDI_WEIGHT)
85 pItem->fWeight = m_arrItems[iItem].fWeight;
86 return TRUE;
87}
88
89BOOL SHeaderCtrl::SetItem(int iItem, const SHDITEM *pItem)
90{
91 if ((UINT)iItem >= m_arrItems.GetCount())
92 return FALSE;
93
94 SHDITEMEX &item = m_arrItems[iItem];
95
96 if (pItem->mask & SHDI_TEXT && pItem->pszText)
97 {
98 item.strText.SetText(pItem->pszText, false);
99 }
100 if (pItem->mask & SHDI_WIDTH)
101 item.cx = pItem->cx;
102 if (pItem->mask & SHDI_LPARAM)
103 item.lParam = pItem->lParam;
104 if (pItem->mask & SHDI_WEIGHT)
105 item.fWeight = pItem->fWeight;
106 if (pItem->mask & SHDI_FORMAT)
107 item.fmt = pItem->fmt;
108 if (pItem->mask & SHDI_VISIBLE)
109 item.bVisible = pItem->bVisible;
110 Invalidate();
111 return TRUE;
112}
113
115{
116 SPainter painter;
117 BeforePaint(pRT, painter);
118 CRect rcClient;
119 GetClientRect(&rcClient);
120 CRect rcItem(rcClient.left, rcClient.top, rcClient.left, rcClient.bottom);
121 for (UINT i = 0; i < m_arrItems.GetCount(); i++)
122 {
123 if (!m_arrItems[i].bVisible)
124 continue;
125 rcItem.left = rcItem.right;
126 rcItem.right = rcItem.left + GetItemWidth(i);
127 DrawItem(pRT, rcItem, m_arrItems.GetData() + i);
128 if (rcItem.right >= rcClient.right)
129 break;
130 }
131 if (rcItem.right < rcClient.right)
132 {
133 rcItem.left = rcItem.right;
134 rcItem.right = rcClient.right;
135 if (m_pSkinItem)
136 m_pSkinItem->DrawByState(pRT, rcItem, WndState_Disable);
137 }
138 AfterPaint(pRT, painter);
139}
140
141void SHeaderCtrl::DrawItem(IRenderTarget *pRT, CRect rcItem, const LPSHDITEMEX pItem)
142{
143 if (!pItem->bVisible)
144 return;
145 if (m_pSkinItem)
146 m_pSkinItem->DrawByState(pRT, rcItem, pItem->state);
147 UINT align = DT_SINGLELINE | DT_VCENTER;
148 if (pItem->fmt & HDF_CENTER)
149 align |= DT_CENTER;
150 else if (pItem->fmt & HDF_RIGHT)
151 align |= DT_RIGHT;
152
153 BOOL bDrawSortFlag = (pItem->fmt & SORT_MASK) != 0 && m_pSkinSort;
154 if (!bDrawSortFlag)
155 {
156 pRT->DrawText(pItem->strText.GetText(FALSE), pItem->strText.GetText(FALSE).GetLength(), rcItem, align);
157 return;
158 }
159
160 CSize szSort = m_pSkinSort->GetSkinSize();
161 rcItem.right -= szSort.cx;
162
163 pRT->DrawText(pItem->strText.GetText(FALSE), pItem->strText.GetText(FALSE).GetLength(), rcItem, align);
164 CPoint ptSort;
165 ptSort.x = rcItem.right;
166 ptSort.y = rcItem.top + (rcItem.Height() - szSort.cy) / 2;
167
168 m_pSkinSort->DrawByIndex(pRT, CRect(ptSort, szSort), (pItem->fmt & HDF_SORTUP) ? 0 : 1);
169}
170
172{
173 if (iItem < 0 || (UINT)iItem >= m_arrItems.GetCount())
174 return FALSE;
175
176 int iOrder = m_arrItems[iItem].iOrder;
177 m_arrItems.RemoveAt(iItem);
178 //更新排序
179 for (UINT i = 0; i < m_arrItems.GetCount(); i++)
180 {
181 if (m_arrItems[i].iOrder > iOrder)
182 m_arrItems[i].iOrder--;
183 }
184 EventHeaderRelayout e(this);
185 FireEvent(e);
186
187 Invalidate();
188 return TRUE;
189}
190
192{
193 m_arrItems.RemoveAll();
194 EventHeaderRelayout e(this);
195 FireEvent(e);
196 Invalidate();
197}
198
206
207CRect SHeaderCtrl::GetItemRect(int iItem) const
208{
209 CRect rcClient;
210 GetClientRect(&rcClient);
211 if (!m_arrItems[iItem].bVisible)
212 return CRect();
213 CRect rcItem(rcClient.left, rcClient.top, rcClient.left, rcClient.bottom);
214 for (int i = 0; i <= iItem && i < (int)m_arrItems.GetCount(); i++)
215 {
216 if (!m_arrItems[i].bVisible)
217 continue;
218 rcItem.left = rcItem.right;
219 rcItem.right = rcItem.left + GetItemWidth(i);
220 }
221 return rcItem;
222}
223
224void SHeaderCtrl::GetItemRect(CTHIS_ int iItem, LPRECT prc) SCONST
225{
226 *prc = GetItemRect(iItem);
227}
228
229int SHeaderCtrl::GetOriItemIndex(int iOrder) const
230{
231 for (UINT i = 0; i < m_arrItems.GetCount(); i++)
232 {
233 if (m_arrItems[i].iOrder == iOrder)
234 return i;
235 }
236 return -1;
237}
238
240{
241 CRect rcItem = GetItemRect(iItem);
243 DrawItem(pRT, rcItem, m_arrItems.GetData() + iItem);
245}
246
247void SHeaderCtrl::OnLButtonDown(UINT nFlags, CPoint pt)
248{
249 SetCapture();
250 m_ptClick = pt;
251
252 m_dwHitTest = HitTest(pt);
254 {
255 if (m_bSortHeader)
256 {
258 RedrawItem(LOWORD(m_dwHitTest));
259 }
260 }
261 else if (m_dwHitTest != -1)
262 {
264 }
265}
266
267void SHeaderCtrl::OnLButtonUp(UINT nFlags, CPoint pt)
268{
270 {
271 if (m_bDragging)
272 { //拖动表头项
274 {
275 SDragWnd::EndDrag();
276 DeleteObject(m_hDragImg);
277 m_hDragImg = NULL;
278
279 m_arrItems[LOWORD(m_dwHitTest)].state = WndState_Normal;
280
282 {
283 SHDITEMEX t = m_arrItems[LOWORD(m_dwHitTest)];
284 m_arrItems.RemoveAt(LOWORD(m_dwHitTest));
285 int nPos = LOWORD(m_dwDragTo);
286 if (nPos > LOWORD(m_dwHitTest))
287 nPos--; //要考虑将自己移除的影响
288 m_arrItems.InsertAt(LOWORD(m_dwDragTo), t);
289 //发消息通知宿主表项位置发生变化
290 EventHeaderItemSwap evt(this);
291 evt.iOldIndex = LOWORD(m_dwHitTest);
292 evt.iNewIndex = nPos;
293 FireEvent(evt);
294
295 EventHeaderRelayout e(this);
296 FireEvent(e);
297 }
298
299 m_dwHitTest = HitTest(pt);
300 m_dwDragTo = (DWORD)-1;
301 Invalidate();
302 }
303 }
304 else
305 { //点击表头项
306 if (m_bSortHeader)
307 {
308 m_arrItems[LOWORD(m_dwHitTest)].state = WndState_Hover;
309 RedrawItem(LOWORD(m_dwHitTest));
310 EventHeaderClick evt(this);
311 evt.iItem = LOWORD(m_dwHitTest);
312 FireEvent(evt);
313 }
314 }
315 }
316 else if (m_dwHitTest != -1)
317 { //调整表头宽度,发送一个调整完成消息
318 EventHeaderItemChanged evt(this);
319 evt.iItem = LOWORD(m_dwHitTest);
320 evt.nWidth = GetItemWidth(evt.iItem);
321 FireEvent(evt);
322
323 EventHeaderRelayout e(this);
324 FireEvent(e);
325 }
326 m_bDragging = FALSE;
328}
329
330void SHeaderCtrl::OnMouseMove(UINT nFlags, CPoint pt)
331{
332 if (m_bDragging || nFlags & MK_LBUTTON)
333 {
334 if (!m_bDragging)
335 {
337 {
339 CRect rcItem = GetItemRect(LOWORD(m_dwHitTest));
342 CPoint pt = m_ptClick - rcItem.TopLeft();
343 SDragWnd::BeginDrag(m_hDragImg, pt, 0, 128, LWA_ALPHA | LWA_COLORKEY);
344 m_bDragging = TRUE;
345 }
346 }
348 {
350 {
351 DWORD dwDragTo = HitTest(pt);
352 CPoint pt2(pt.x, m_ptClick.y);
353 ClientToScreen(GetContainer()->GetHostHwnd(), &pt2);
354 if (IsItemHover(dwDragTo) && m_dwDragTo != dwDragTo)
355 {
356 m_dwDragTo = dwDragTo;
357 DrawDraggingState(dwDragTo);
358 }
359 SDragWnd::DragMove(pt2);
360 }
361 }
362 else if (m_dwHitTest != -1)
363 { //调节宽度
364 if (!m_bFixWidth)
365 {
366 int iItem = LOWORD(m_dwHitTest);
367 int cxNew = m_nAdjItemOldWidth + pt.x - m_ptClick.x;
368 if (cxNew < 0)
369 cxNew = 0;
370 CRect rc = GetClientRect();
371 int nTotalWid = 0;
372 float fTotalWeight = 0.0f;
373 for (UINT i = 0; i < m_arrItems.GetCount(); i++)
374 {
375 if (!m_arrItems[i].bVisible)
376 continue;
377 nTotalWid += m_arrItems[i].cx;
378 fTotalWeight += m_arrItems[i].fWeight;
379 }
380 if (fTotalWeight > 0.0f)
381 {
382 if (nTotalWid != rc.Width())
383 { // first adjust, split the remain size into columns based on column weight.
384 int nRemain = rc.Width() - nTotalWid;
385 for (UINT i = 0; i < m_arrItems.GetCount() && nRemain > 0 && fTotalWeight > 0.0f; i++)
386 {
387 if (!m_arrItems[i].bVisible)
388 continue;
389 int nAppend = (int)(nRemain * m_arrItems[i].fWeight / fTotalWeight);
390 m_arrItems[i].cx += nAppend;
391 nRemain -= nAppend;
392 fTotalWeight -= m_arrItems[i].fWeight;
393 }
394 }
395 if (iItem == m_arrItems.GetCount() - 1) // can't adjust last column
396 return;
397 int nDelta = cxNew - m_arrItems[iItem].cx;
398 if (m_arrItems[iItem].cx + nDelta < 0)
399 nDelta = -m_arrItems[iItem].cx;
400 if (m_arrItems[iItem + 1].cx - nDelta < 0)
401 nDelta = m_arrItems[iItem + 1].cx;
402 m_arrItems[iItem].cx += nDelta; // add the delta the the select column.
403 m_arrItems[iItem + 1].cx -= nDelta; // sub the delta from the next column.
404 }
405 else
406 { // no weight data
407 m_arrItems[iItem].cx = cxNew;
408 }
409
410 Invalidate();
411 //发出调节宽度消息
412 EventHeaderItemChanging evt(this);
413 evt.iItem = iItem;
414 evt.nWidth = cxNew;
415 FireEvent(evt);
416
417 EventHeaderRelayout e(this);
418 FireEvent(e);
419 }
420 }
421 }
422 else
423 {
424 DWORD dwHitTest = HitTest(pt);
425 if (dwHitTest != m_dwHitTest)
426 {
427 if (m_bSortHeader)
428 {
430 {
431 WORD iHover = LOWORD(m_dwHitTest);
432 m_arrItems[iHover].state = WndState_Normal;
433 RedrawItem(iHover);
434 }
435 if (IsItemHover(dwHitTest))
436 {
437 WORD iHover = LOWORD(dwHitTest);
438 m_arrItems[iHover].state = WndState_Hover;
439 RedrawItem(iHover);
440 }
441 }
442
443 m_dwHitTest = dwHitTest;
444 }
445 }
446}
447
449{
450 if (!m_bDragging)
451 {
453 {
454 if (m_bSortHeader)
455 {
456 m_arrItems[LOWORD(m_dwHitTest)].state = WndState_Normal;
457 RedrawItem(LOWORD(m_dwHitTest));
458 }
459 m_dwHitTest = (DWORD)-1;
460 }
461 }
462}
463
465{
466 SXmlNode xmlItems = xmlNode.child(L"items");
467 if (xmlItems)
468 xmlItems.set_userdata(1);
469 __baseCls::CreateChildren(xmlNode);
470
471 if (!xmlItems)
472 return FALSE;
473 SXmlNode xmlItem = xmlItems.child(L"item");
474 int iOrder = 0;
475 while (xmlItem)
476 {
477 SHDITEMEX item;
478 item.strText.SetOwner(this);
479 item.mask = 0xFFFFFFFF;
480 item.iOrder = iOrder++;
481 SStringW strText = xmlItem.attribute(L"text").as_string();
482 if (strText.IsEmpty())
483 {
484 strText = SWindow::GetXmlText(xmlItem);
485 }
486 item.strText.SetText(S_CW2T(GETSTRING(strText)));
487 SLayoutSize szItem = GETLAYOUTSIZE(xmlItem.attribute(L"width").as_string(L"50"));
488 item.cx = szItem.toPixelSize(GetScale());
489 item.fWeight = xmlItem.attribute(L"weight").as_float();
490 item.bDpiAware = (szItem.unit != SLayoutSize::px);
491 item.lParam = xmlItem.attribute(L"userData").as_uint(0);
492 item.bVisible = xmlItem.attribute(L"visible").as_bool(true);
493 item.fmt = 0;
494 item.state = 0;
495 SStringW strSort = xmlItem.attribute(L"sortFlag").as_string();
496 strSort.MakeLower();
497 if (strSort == L"down")
498 item.fmt |= HDF_SORTDOWN;
499 else if (strSort == L"up")
500 item.fmt |= HDF_SORTUP;
501 SStringW strAlign = xmlItem.attribute(L"align").as_string();
502 strAlign.MakeLower();
503 if (strAlign == L"left")
504 item.fmt |= HDF_LEFT;
505 else if (strAlign == L"center")
506 item.fmt |= HDF_CENTER;
507 else if (strAlign == L"right")
508 item.fmt |= HDF_RIGHT;
509 else
510 {
511 int align = GetStyle().GetTextAlign();
512 if (align & DT_CENTER)
513 item.fmt |= HDF_CENTER;
514 else if (align & DT_RIGHT)
515 item.fmt |= HDF_RIGHT;
516 else
517 item.fmt |= HDF_LEFT;
518 }
519 m_arrItems.InsertAt(m_arrItems.GetCount(), item);
520
521 xmlItem = xmlItem.next_sibling(L"item");
522 }
523
524 return TRUE;
525}
526
527BOOL SHeaderCtrl::OnSetCursor(const CPoint &pt)
528{
529 if (m_bFixWidth)
530 return FALSE;
531 DWORD dwHit = HitTest(pt);
532 if (HIWORD(dwHit) == LOWORD(dwHit))
533 return FALSE;
534 HCURSOR hCursor = GETRESPROVIDER->LoadCursor(IDC_SIZEWE);
535 SetCursor(hCursor);
536 return TRUE;
537}
538
539DWORD SHeaderCtrl::HitTest(CPoint pt)
540{
541 CRect rcClient;
542 GetClientRect(&rcClient);
543 if (!rcClient.PtInRect(pt))
544 return (DWORD)-1;
545
546 CRect rcItem(rcClient.left, rcClient.top, rcClient.left, rcClient.bottom);
547 int nMargin = m_bFixWidth ? MARGIN_ADJUST_DISABLE : MARGIN_ADJUST_ENABLE;
548 for (UINT i = 0; i < m_arrItems.GetCount(); i++)
549 {
550 if (m_arrItems[i].cx == 0 || !m_arrItems[i].bVisible)
551 continue; //越过宽度为0的项
552
553 rcItem.left = rcItem.right;
554 rcItem.right = rcItem.left + GetItemWidth(i);
555 if (pt.x < rcItem.left + nMargin)
556 {
557 int nLeft = i > 0 ? i - 1 : 0;
558 return MAKELONG(nLeft, i);
559 }
560 else if (pt.x < rcItem.right - nMargin)
561 {
562 return MAKELONG(i, i);
563 }
564 else if (pt.x < rcItem.right)
565 {
566 WORD nRight = (WORD)i + 1;
567 if (nRight >= m_arrItems.GetCount())
568 nRight = (WORD)-1; //采用-1代表末尾
569 return MAKELONG(i, nRight);
570 }
571 }
572 return (DWORD)-1;
573}
574
576{
577 if (iItem >= m_arrItems.GetCount())
578 return NULL;
579 CRect rcClient;
580 GetClientRect(rcClient);
581 CRect rcItem(0, 0, GetItemWidth(iItem), rcClient.Height());
582
584 GETRENDERFACTORY->CreateRenderTarget(&pRT, rcItem.Width(), rcItem.Height());
585 pRT->BeginDraw();
586 BeforePaintEx(pRT);
587 DrawItem(pRT, rcItem, m_arrItems.GetData() + iItem);
588 pRT->EndDraw();
589
590 HBITMAP hBmp = CreateBitmap(rcItem.Width(), rcItem.Height(), 1, 32, NULL);
591 HDC hdc = GetDC(NULL);
592 HDC hMemDC = CreateCompatibleDC(hdc);
593 ::SelectObject(hMemDC, hBmp);
594 HDC hdcSrc = pRT->GetDC(0);
595 ::BitBlt(hMemDC, 0, 0, rcItem.Width(), rcItem.Height(), hdcSrc, 0, 0, SRCCOPY);
596 pRT->ReleaseDC(hdcSrc, NULL);
597 DeleteDC(hMemDC);
598 ReleaseDC(NULL, hdc);
599 return hBmp;
600}
601
603{
604 CRect rcClient;
605 GetClientRect(&rcClient);
607 SPainter painter;
608 BeforePaint(pRT, painter);
609 CRect rcItem(rcClient.left, rcClient.top, rcClient.left, rcClient.bottom);
610 int iDragTo = LOWORD(dwDragTo);
611 int iDragFrom = LOWORD(m_dwHitTest);
612
613 SArray<UINT> items;
614 for (UINT i = 0; i < m_arrItems.GetCount(); i++)
615 {
616 if (i != (UINT)iDragFrom)
617 items.Add(i);
618 }
619 items.InsertAt(iDragTo, iDragFrom);
620
621 if (m_pSkinItem)
622 m_pSkinItem->DrawByIndex(pRT, rcClient, 0);
623 for (UINT i = 0; i < items.GetCount(); i++)
624 {
625 rcItem.left = rcItem.right;
626 rcItem.right = rcItem.left + GetItemWidth(items[i]);
627 if (items[i] != (UINT)iDragFrom)
628 DrawItem(pRT, rcItem, m_arrItems.GetData() + items[i]);
629 }
630 AfterPaint(pRT, painter);
632}
633
634int SHeaderCtrl::GetTotalWidth(BOOL bMinWid) const
635{
636 CRect rc = GetClientRect();
637
638 int nTotalWidth = 0;
639 float fTotalWeight = 0.0f;
640 for (UINT i = 0; i < m_arrItems.GetCount(); i++)
641 {
642 if (!m_arrItems[i].bVisible)
643 continue;
644 nTotalWidth += m_arrItems[i].cx;
645 fTotalWeight += m_arrItems[i].fWeight;
646 }
647 if (!bMinWid && fTotalWeight > 0.0f)
648 {
649 return smax(nTotalWidth, rc.Width());
650 }
651 else
652 {
653 return nTotalWidth;
654 }
655}
656
657int SHeaderCtrl::GetItemWidth(int iItem) const
658{
659 if (iItem < 0 || (UINT)iItem >= m_arrItems.GetCount())
660 return -1;
661 if (!m_arrItems[iItem].bVisible)
662 return 0;
663 const SHDITEM &item = m_arrItems[iItem];
664 if (SLayoutSize::fequal(item.fWeight, 0.0f))
665 return item.cx;
666 else
667 {
668 CRect rc = GetClientRect();
669 if (rc.IsRectEmpty())
670 {
671 return item.cx;
672 }
673 else
674 {
675 float fTotalWeight = 0.0f;
676 int nTotalWidth = 0;
677 for (UINT i = 0; i < m_arrItems.GetCount(); i++)
678 {
679 if (!m_arrItems[i].bVisible)
680 continue;
681 fTotalWeight += m_arrItems[i].fWeight;
682 nTotalWidth += m_arrItems[i].cx;
683 }
684 int nRemain = rc.Width() - nTotalWidth;
685 if (nRemain <= 0)
686 {
687 return m_arrItems[iItem].cx;
688 }
689 for (int i = 0; i < iItem; i++)
690 {
691 if (!m_arrItems[i].bVisible)
692 continue;
693 int nAppend = (int)(nRemain * m_arrItems[i].fWeight / fTotalWeight);
694 nRemain -= nAppend;
695 fTotalWeight -= m_arrItems[i].fWeight;
696 }
697 return item.cx + (int)(nRemain * item.fWeight / fTotalWeight);
698 }
699 }
700}
701
702void SHeaderCtrl::OnActivateApp(BOOL bActive, DWORD dwThreadID)
703{
704 if (m_bDragging)
705 {
706 if (m_bSortHeader && m_dwHitTest != -1)
707 {
708 m_arrItems[LOWORD(m_dwHitTest)].state = WndState_Normal;
709 }
710 m_dwHitTest = (DWORD)-1;
711
712 SDragWnd::EndDrag();
713 DeleteObject(m_hDragImg);
714 m_hDragImg = NULL;
715 m_bDragging = FALSE;
717 Invalidate();
718 }
719}
720
721void SHeaderCtrl::SetItemSort(int iItem, UINT sortFlag)
722{
723 SASSERT(iItem >= 0 && iItem < (int)m_arrItems.GetCount());
724
725 if ((sortFlag & SORT_MASK) != (m_arrItems[iItem].fmt & SORT_MASK))
726 {
727 m_arrItems[iItem].fmt &= ~SORT_MASK;
728 m_arrItems[iItem].fmt |= sortFlag & SORT_MASK;
729 CRect rcItem = GetItemRect(iItem);
730 InvalidateRect(rcItem);
731 }
732}
733
734void SHeaderCtrl::OnColorize(COLORREF cr)
735{
736 __baseCls::OnColorize(cr);
737 if (m_pSkinItem)
738 m_pSkinItem->OnColorize(cr);
739 if (m_pSkinSort)
740 m_pSkinSort->OnColorize(cr);
741}
742
744{
745 __baseCls::OnLanguageChanged();
746 for (UINT i = 0; i < m_arrItems.GetCount(); i++)
747 {
748 m_arrItems[i].strText.TranslateText();
749 }
750 return S_OK;
751}
752
754{
756 if (nScale != m_nScale)
757 {
758 for (size_t i = 0; i < m_arrItems.GetCount(); i++)
759 {
760 if (!m_arrItems[i].bDpiAware)
761 continue;
762 m_arrItems[i].cx = m_arrItems[i].cx * nScale / m_nScale;
763 }
764 m_nScale = nScale;
765 }
766}
767
768BOOL SHeaderCtrl::OnRelayout(const CRect &rcWnd)
769{
770 BOOL bRet = __baseCls::OnRelayout(rcWnd);
771 if (bRet)
772 {
773 EventHeaderRelayout e(this);
774 FireEvent(e);
775 }
776 return bRet;
777}
778
779void SHeaderCtrl::SetItemVisible(int iItem, BOOL visible)
780{
781 SASSERT(iItem >= 0 && iItem < (int)m_arrItems.GetCount());
782 m_arrItems[iItem].bVisible = visible;
783
784 Invalidate();
785 //发出调节宽度消息
786 EventHeaderItemChanged evt(this);
787 evt.iItem = iItem;
788 evt.nWidth = GetItemWidth(iItem);
789 FireEvent(evt);
790}
791
792BOOL SHeaderCtrl::IsItemVisible(int iItem) const
793{
794 SASSERT(iItem >= 0 && iItem < (int)m_arrItems.GetCount());
795 return m_arrItems[iItem].bVisible;
796}
797
799{
800 for (UINT i = 0; i < m_arrItems.GetCount(); i++)
801 {
802 if (m_arrItems[i].fWeight > 0.0f)
803 return TRUE;
804 }
805 return FALSE;
806}
807
809{
810 return (UINT)m_arrItems.GetCount();
811}
812
813SNSEND
@ WndState_Hover
Definition SWnd.h:76
@ WndState_Disable
Definition SWnd.h:80
@ WndState_Normal
Definition SWnd.h:75
@ WndState_PushDown
Definition SWnd.h:77
@ GRT_PAINTBKGND
Smart pointer class for managing COM-style reference-counted objects.
void setMutedState(BOOL setting)
设置事件集的静音状态
BOOL IsItemHover(DWORD dwHitTest)
Check if an item is in hover state.
void OnActivateApp(BOOL bActive, DWORD dwThreadID)
Handle activate application event.
virtual void OnScaleChanged(int nScale)
Handle scale change event.
HBITMAP CreateDragImage(UINT iItem)
Create a drag image for an item.
int InsertItem(int iItem, LPCTSTR pszText, int nWidth, UINT fmt, LPARAM lParam, BOOL bDpiAware=FALSE, float fWeight=0.0f) OVERRIDE
Insert a new item.
void GetItemRect(int iItem, LPRECT prc) SCONST OVERRIDE
Get the rectangle of an item.
void OnLButtonDown(UINT nFlags, CPoint pt)
Handle left mouse button down event.
HBITMAP m_hDragImg
CPoint m_ptClick
BOOL IsItemVisible(int iItem) SCONST OVERRIDE
Check if an item is visible.
int GetItemWidth(int iItem) SCONST OVERRIDE
Get the width of a specific item.
void SetItemVisible(int iItem, BOOL visible) OVERRIDE
Set the visibility of an item.
BOOL m_bItemSwapEnable
virtual HRESULT OnLanguageChanged()
Handle language change event.
void SetItemSort(int iItem, UINT sortFlag) OVERRIDE
Set the sort flag for an item.
BOOL IsAutoResize() SCONST OVERRIDE
Check if auto-resize is enabled.
DWORD m_dwHitTest
void OnLButtonUp(UINT nFlags, CPoint pt)
Handle left mouse button up event.
int GetTotalWidth(BOOL bMinWid=FALSE) SCONST OVERRIDE
Get the total width of all items.
DWORD HitTest(CPoint pt)
Hit test to determine the item under the mouse.
void RedrawItem(int iItem)
Redraw a specific item.
SArray< SHDITEMEX > m_arrItems
virtual BOOL CreateChildren(SXmlNode xmlNode)
Create child items from XML configuration.
void OnDestroy()
Handle destroy event.
DWORD m_dwDragTo
SHeaderCtrl(void)
Constructor.
void DeleteAllItems() OVERRIDE
Delete all items.
void OnMouseMove(UINT nFlags, CPoint pt)
Handle mouse move event.
int m_nAdjItemOldWidth
virtual BOOL OnSetCursor(const CPoint &pt)
Set the cursor based on the mouse position.
BOOL SetItem(int iItem, const SHDITEM *pItem) OVERRIDE
Set an item.
SAutoRefPtr< ISkinObj > m_pSkinSort
BOOL GetItem(int iItem, SHDITEM *pItem) SCONST OVERRIDE
Get an item.
void OnPaint(IRenderTarget *pRT)
Paint the control.
UINT GetItemCount() SCONST OVERRIDE
Get the number of items.
SAutoRefPtr< ISkinObj > m_pSkinItem
BOOL m_bSortHeader
virtual BOOL OnRelayout(const CRect &rcWnd)
Handle relayout event.
void OnMouseLeave()
Handle mouse leave event.
int GetOriItemIndex(int iOrder) SCONST OVERRIDE
Get the original item index from the order.
BOOL DeleteItem(int iItem) OVERRIDE
Delete a specific item.
virtual void DrawItem(IRenderTarget *pRT, CRect rcItem, const LPSHDITEMEX pItem)
Draw an item.
~SHeaderCtrl(void)
Destructor.
void DrawDraggingState(DWORD dwDragTo)
Draw the dragging state.
virtual void OnColorize(COLORREF cr)
Handle colorization event.
布局大小类
Definition SLayoutSize.h:10
static bool fequal(float a, float b)
比较两个浮点数是否相等
int toPixelSize(int scale) const
将大小转换为像素值
Helper class for painting.
Definition SWnd.h:178
A class representing an ASCII string.
Definition sstringw.h:96
BOOL IsEmpty() SCONST
Checks if the string is empty.
SStringW & MakeLower()
Converts the string to lowercase.
Definition sstringw.cpp:869
void SetOwner(SWindow *pOwner)
Sets the owner window.
Definition Swnd.cpp:25
void SetText(const SStringT &strText, bool bAutoEscape=true)
Sets the text.
Definition Swnd.cpp:35
SStringT GetText(BOOL bRawText=FALSE) const
Gets the text.
Definition Swnd.cpp:30
BOOL FireEvent(IEvtArgs *evt) OVERRIDE
Fires an event.
Definition Swnd.cpp:1540
void OnDestroy()
Handles the destruction of the window.
Definition Swnd.cpp:1701
void ReleaseRenderTarget(IRenderTarget *pRT)
Releases the RenderTarget obtained via GetRenderTarget.
Definition Swnd.cpp:2372
int GetScale() SCONST OVERRIDE
Retrieves the scale factor of the window.
Definition Swnd.cpp:3266
virtual void OnScaleChanged(int scale)
Called when the scale of the window changes.
Definition Swnd.cpp:3271
ISwndContainer * GetContainer() OVERRIDE
Retrieves the container associated with this window.
Definition Swnd.cpp:679
virtual CRect GetClientRect() const
Retrieves the client rectangle of the window.
Definition Swnd.cpp:243
virtual void BeforePaint(IRenderTarget *pRT, SPainter &painter)
Prepare rendering environment.
Definition Swnd.cpp:1755
static SStringW GetXmlText(const SXmlNode &xmlNode)
Gets the XML text from a node.
Definition Swnd.cpp:2955
void InvalidateRect(LPCRECT lprect) OVERRIDE
Invalidates a specific rectangle area of the window.
Definition Swnd.cpp:1444
SWND SetCapture() OVERRIDE
Sets the window to capture the mouse.
Definition Swnd.cpp:2484
virtual void AfterPaint(IRenderTarget *pRT, SPainter &painter)
Restore rendering environment.
Definition Swnd.cpp:1776
SEventSet * GetEventSet()
Retrieves the event set associated with the window.
Definition SWnd.h:1290
void Invalidate() OVERRIDE
Invalidates the entire window.
Definition Swnd.cpp:1437
SEventSet m_evtSet
Definition SWnd.h:2581
const SwndStyle & GetStyle() const
Retrieves the style of the window.
Definition Swnd.cpp:716
HWND GetHostHwnd() OVERRIDE
Retrieves the host window handle.
Definition Swnd.cpp:3616
void BeforePaintEx(IRenderTarget *pRT)
Prepares the drawing environment for the current window's RenderTarget, starting from the top-level w...
Definition Swnd.cpp:1767
BOOL m_bClipClient
Definition SWnd.h:2607
BOOL ReleaseCapture() OVERRIDE
Releases the mouse capture from the window.
Definition Swnd.cpp:2491
IRenderTarget * GetRenderTarget(LPCRECT pRc=NULL, GrtFlag gdcFlags=GRT_NODRAW, BOOL bClientRT=TRUE)
Retrieves a memory DC compatible with the SWND window.
Definition Swnd.cpp:2320
float as_float(float def=0) const
Converts the attribute value to a float.
Definition SXml.cpp:115
const wchar_t * as_string(const wchar_t *def=L"") const
Gets the attribute value as a string.
Definition SXml.cpp:95
unsigned int as_uint(unsigned int def=0) const
Converts the attribute value to an unsigned integer.
Definition SXml.cpp:105
bool as_bool(bool def=false) const
Converts the attribute value to a boolean.
Definition SXml.cpp:120
Class representing an XML node.
Definition SXml.h:352
SXmlNode next_sibling() const
Gets the next sibling node in the children list of the parent node.
Definition SXml.cpp:393
SXmlAttr attribute(const wchar_t *name, bool bCaseSensitive=false) const
Gets the attribute with the specified name.
Definition SXml.cpp:428
SXmlNode child(const wchar_t *name, bool bCaseSensitive=false) const
Gets the child node, attribute, or next/previous sibling with the specified name.
Definition SXml.cpp:423
BOOL set_userdata(int data) OVERRIDE
Sets user data for the node.
Definition SXml.cpp:270
UINT GetTextAlign() const
Retrieves the text alignment.
Definition SwndStyle.cpp:36
Interface for rendering target objects.
Definition SRender-i.h:1440
HRESULT DrawText(LPCTSTR pszText, int cchLen, LPRECT pRc, UINT uFormat) PURE
Draw text within a rectangle.