topbanner_forum
  *

avatar image

Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length
  • Friday March 29, 2024, 4:21 am
  • Proudly celebrating 15+ years online.
  • Donate now to become a lifetime supporting member of the site and get a non-expiring license key for all of our programs.
  • donate

Author Topic: Contrary ListView Control  (Read 3311 times)

Stoic Joker

  • Honorary Member
  • Joined in 2008
  • **
  • Posts: 6,646
    • View Profile
    • Donate to Member
Contrary ListView Control
« on: October 16, 2010, 02:16 PM »
Okay, so I've had this nagging ongoing issue with ListView control behavior for a year or so. I thought I'd find a fix for it eventually...But damn-it that's taking too long :)

Here's the rub. I have a standard ListView control that has the grid lines alternate color going down to make it easier to read. Now this control works just fine right up until I add the (below code) use XP style controls line to stdafx.h.
Code: C++ [Select]
  1. // This line Allows the Application to Use the XP Themes Control Styles!
  2. #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")

Then it becomes completely EviL; when program starts all the lines are white, and the last line of the report is a complete artifact nightmare. Below pic is of two different copies of Page Countster, both with the same report open to demonstrate the issue. The top copy is with out the above code, and looks fine. The bottom copy contains the above (XP style controls) code and has an echo of the last line of the report as an artifact that appears to be a line that isn't quite scrolled into view. It also opens as plain white and screws-up the last few lines of the report leaving them as all gray.

ListView Madness.jpg

I've tried calling InvalidateRect(...) in a variety of places that caused the control to flicker so badly it was a seizure risk...But still no joy.


What am I missing?

Stoic Joker

  • Honorary Member
  • Joined in 2008
  • **
  • Posts: 6,646
    • View Profile
    • Donate to Member
Re: Contrary ListView Control
« Reply #1 on: October 17, 2010, 08:33 AM »
Hm... Okay, I'll assume by the lack of response that there's not enough information. So here's (the code I'm working with) a bit more detail:

ListView control is subclassed in WM_CREATE like so:
Code: C++ [Select]
  1. /////////////////////////////////////////////////////////////
  2.  
  3.         prevWndFunc = (FARPROC)(LONG_PTR)GetWindowLong (g_hListBox, GWL_WNDPROC);
  4.         SetWindowLong (g_hListBox, GWL_WNDPROC, (LONG)(LRESULT)ListViewWndProc);
  5.  
  6. /////////////////////////////////////////////////////////////

And here is the procedure:
Code: C++ [Select]
  1. #include "stdafx.h"
  2.  
  3. #define ROW_SHADE 90
  4. extern FARPROC  prevWndFunc;
  5.  //=========================================================
  6. //-> create a lighter shade (by fPercent %) of a given color
  7. COLORREF colorShade(COLORREF c, BYTE fPercent) {
  8.   return RGB((GetRValue (c) * fPercent / 100.0),
  9.                          (GetGValue (c) * fPercent / 100.0),
  10.                          (GetBValue (c) * fPercent / 100.0));
  11. }
  12.  //====================================================
  13. //-> re-draw rows with the appropriate background color
  14. void PaintAlternatingRows(HWND hWnd) {
  15.         int     iItems, iTop;
  16.         RECT    rectDestin,     //      temporary storage
  17.                         rectUpd,        //      rectangle to update
  18.                         rect;           //      row rectangle
  19.         POINT   pt;                     //  >>>--->.<---<<<
  20.         COLORREF c;                     //      temporary storage
  21.  
  22. //      get the rectangle to be updated
  23.         GetUpdateRect(hWnd, &rectUpd, FALSE);
  24. //      allow default processing first
  25.         CallWindowProc((WNDPROC)prevWndFunc, hWnd, WM_PAINT, 0, 0);
  26. // set the row horizontal dimensions
  27.         SetRect(&rect, rectUpd.left, 0, rectUpd.right, 0);
  28. //      number of displayed rows
  29.         iItems = ListView_GetCountPerPage(hWnd);
  30. //      first visible row
  31.         iTop = ListView_GetTopIndex(hWnd);
  32.  
  33.         ListView_GetItemPosition(hWnd, iTop, &pt);
  34.         for(int i=iTop ; i<=iTop+iItems ; i++) {
  35.                 char szPCount[MIN_BUFF] = {0};
  36. //              set row vertical dimensions
  37.                 rect.top = pt.y;
  38.                 ListView_GetItemPosition(hWnd, i+1, &pt);
  39.                 rect.bottom = pt.y;
  40. //              if row rectangle intersects update rectangle then it requires re-drawing
  41.                 if(IntersectRect(&rectDestin, &rectUpd, &rect)) {
  42. //                      change text background colour accordingly
  43.                         c = (i % 2) ?
  44.                                 colorShade(GetSysColor(COLOR_WINDOW), ROW_SHADE) :
  45.                                 GetSysColor(COLOR_WINDOW);
  46.                         ListView_SetTextBkColor(hWnd, c);
  47. //-------------------------------------------------------------------------------------------->
  48.                         ListView_GetItemText(hWnd, i, 5, szPCount, sizeof(szPCount));
  49.                         if(strcmp(szPCount, "OffLine!")) { //---++++++---> String Match = 0 <-> So...
  50.                                 ListView_SetTextColor(hWnd, CLR_DEFAULT); //-> OnLine Printers Stay Black
  51.                         }else{ //------------------------------------------------->     ...and...
  52.                                 ListView_SetTextColor(hWnd, RGB(255, 0, 0)); // OffLine Printers Turn Red
  53.                         }
  54. //-------------------------------------------------------------------------------------------->
  55. //                      invalidate the row rectangle then...
  56.                         InvalidateRect(hWnd, &rect, FALSE);
  57. //                      ...force default processing
  58.                         CallWindowProc((WNDPROC)prevWndFunc, hWnd, WM_PAINT, 0, 0);
  59.                 }
  60.         }
  61. }
  62. //      re-draw row backgrounds with the appropriate background colour
  63. void EraseAlternatingRowBkgnds(HWND hWnd, HDC hDC) {
  64.         int     iItems, iTop;
  65.         HBRUSH  brushCol1,      //      1st color
  66.                         brushCol2;      //      2nd color
  67.         RECT    rect;           //      row rectangle
  68.         POINT   pt;
  69.  
  70. //      create colored brushes
  71.         brushCol1 = CreateSolidBrush(GetSysColor(COLOR_WINDOW));
  72.         brushCol2 = CreateSolidBrush(colorShade(GetSysColor(COLOR_WINDOW), ROW_SHADE));
  73. //      get horizontal dimensions of row
  74.         GetClientRect(hWnd, &rect);
  75. //      number of displayed rows
  76.         iItems = ListView_GetCountPerPage(hWnd);
  77. //      first visible row
  78.         iTop = ListView_GetTopIndex(hWnd);
  79.         ListView_GetItemPosition(hWnd, iTop, &pt);
  80.  
  81.         for(int i=iTop; i<=iTop+iItems; i++) {
  82. //              set row vertical dimensions
  83.                 rect.top = pt.y;
  84.                 ListView_GetItemPosition(hWnd, i+1, &pt);
  85.                 rect.bottom = pt.y;
  86. //              fill row with appropriate color
  87.                 FillRect(hDC, &rect, (i % 2) ? brushCol2 : brushCol1);
  88.         }
  89.        
  90. //      cleanup
  91.         DeleteObject(brushCol1);
  92.         DeleteObject(brushCol2);
  93. }
  94.  //=======================================================================================
  95. //-----------------------------------------------------------> SubClassed Window Procedure
  96. LRESULT CALLBACK ListViewWndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam) {
  97.         switch(iMessage) {
  98.                 case WM_PAINT:
  99. //                      intercept the WM_PAINT message which is called each time an area
  100. //                      of the control's client area requires re-drawing
  101.                         PaintAlternatingRows(hWnd);
  102.                         return 0;
  103.                 case WM_ERASEBKGND:
  104. //                      intercept the WM_ERASEBKGRN message which is called each time an area
  105. //                      of the control's client area background requires re-drawing
  106.                         EraseAlternatingRowBkgnds(hWnd, (HDC) wParam);
  107.                         return 0;
  108.         }
  109.   // continue with default message processing
  110.   return CallWindowProc((WNDPROC)prevWndFunc, hWnd, iMessage, wParam, lParam);
  111. }