ATTENTION: You are viewing a page formatted for mobile devices; to view the full web page, click HERE.

Other Software > Developer's Corner

Contrary ListView Control

(1/1)

Stoic Joker:
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++ ---// This line Allows the Application to Use the XP Themes Control Styles!#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.



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:
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++ ---/////////////////////////////////////////////////////////////         prevWndFunc = (FARPROC)(LONG_PTR)GetWindowLong (g_hListBox, GWL_WNDPROC);        SetWindowLong (g_hListBox, GWL_WNDPROC, (LONG)(LRESULT)ListViewWndProc); /////////////////////////////////////////////////////////////
And here is the procedure:
--- Code: C++ ---#include "stdafx.h" #define ROW_SHADE 90extern FARPROC  prevWndFunc; //=========================================================//-> create a lighter shade (by fPercent %) of a given colorCOLORREF colorShade(COLORREF c, BYTE fPercent) {  return RGB((GetRValue (c) * fPercent / 100.0),                         (GetGValue (c) * fPercent / 100.0),                         (GetBValue (c) * fPercent / 100.0));} //====================================================//-> re-draw rows with the appropriate background colorvoid PaintAlternatingRows(HWND hWnd) {        int     iItems, iTop;        RECT    rectDestin,     //      temporary storage                        rectUpd,        //      rectangle to update                        rect;           //      row rectangle        POINT   pt;                     //  >>>--->.<---<<<        COLORREF c;                     //      temporary storage //      get the rectangle to be updated        GetUpdateRect(hWnd, &rectUpd, FALSE);//      allow default processing first        CallWindowProc((WNDPROC)prevWndFunc, hWnd, WM_PAINT, 0, 0);// set the row horizontal dimensions        SetRect(&rect, rectUpd.left, 0, rectUpd.right, 0);//      number of displayed rows        iItems = ListView_GetCountPerPage(hWnd);//      first visible row        iTop = ListView_GetTopIndex(hWnd);         ListView_GetItemPosition(hWnd, iTop, &pt);        for(int i=iTop ; i<=iTop+iItems ; i++) {                char szPCount[MIN_BUFF] = {0};//              set row vertical dimensions                rect.top = pt.y;                ListView_GetItemPosition(hWnd, i+1, &pt);                rect.bottom = pt.y;//              if row rectangle intersects update rectangle then it requires re-drawing                if(IntersectRect(&rectDestin, &rectUpd, &rect)) {//                      change text background colour accordingly                        c = (i % 2) ?                                colorShade(GetSysColor(COLOR_WINDOW), ROW_SHADE) :                                GetSysColor(COLOR_WINDOW);                        ListView_SetTextBkColor(hWnd, c);//-------------------------------------------------------------------------------------------->                        ListView_GetItemText(hWnd, i, 5, szPCount, sizeof(szPCount));                        if(strcmp(szPCount, "OffLine!")) { //---++++++---> String Match = 0 <-> So...                                ListView_SetTextColor(hWnd, CLR_DEFAULT); //-> OnLine Printers Stay Black                        }else{ //------------------------------------------------->     ...and...                                ListView_SetTextColor(hWnd, RGB(255, 0, 0)); // OffLine Printers Turn Red                        }//-------------------------------------------------------------------------------------------->//                      invalidate the row rectangle then...                        InvalidateRect(hWnd, &rect, FALSE);//                      ...force default processing                        CallWindowProc((WNDPROC)prevWndFunc, hWnd, WM_PAINT, 0, 0);                }        }}//      re-draw row backgrounds with the appropriate background colourvoid EraseAlternatingRowBkgnds(HWND hWnd, HDC hDC) {        int     iItems, iTop;        HBRUSH  brushCol1,      //      1st color                        brushCol2;      //      2nd color        RECT    rect;           //      row rectangle        POINT   pt; //      create colored brushes        brushCol1 = CreateSolidBrush(GetSysColor(COLOR_WINDOW));        brushCol2 = CreateSolidBrush(colorShade(GetSysColor(COLOR_WINDOW), ROW_SHADE));//      get horizontal dimensions of row        GetClientRect(hWnd, &rect);//      number of displayed rows        iItems = ListView_GetCountPerPage(hWnd);//      first visible row        iTop = ListView_GetTopIndex(hWnd);        ListView_GetItemPosition(hWnd, iTop, &pt);         for(int i=iTop; i<=iTop+iItems; i++) {//              set row vertical dimensions                rect.top = pt.y;                ListView_GetItemPosition(hWnd, i+1, &pt);                rect.bottom = pt.y;//              fill row with appropriate color                FillRect(hDC, &rect, (i % 2) ? brushCol2 : brushCol1);        }        //      cleanup        DeleteObject(brushCol1);        DeleteObject(brushCol2);} //=======================================================================================//-----------------------------------------------------------> SubClassed Window ProcedureLRESULT CALLBACK ListViewWndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam) {        switch(iMessage) {                case WM_PAINT://                      intercept the WM_PAINT message which is called each time an area//                      of the control's client area requires re-drawing                        PaintAlternatingRows(hWnd);                        return 0;                case WM_ERASEBKGND://                      intercept the WM_ERASEBKGRN message which is called each time an area//                      of the control's client area background requires re-drawing                        EraseAlternatingRowBkgnds(hWnd, (HDC) wParam);                        return 0;        }   // continue with default message processing  return CallWindowProc((WNDPROC)prevWndFunc, hWnd, iMessage, wParam, lParam);}

Navigation

[0] Message Index

Go to full version