zamtmn/metadarkstyle

Remaining prob after TListView Header fix april 11th: missing sort direction indicator

klaus101 opened this issue · 11 comments

'After the fix April 11th 692245c the TListView appears with good background and font colors, in the main form as well as in sub forms.

In the version April 7th it still had been painted, but the bg color was purely black and, so, not fully appropriate to the dark theme.
zamtmn, do you see a possibility that it might be fixed too, as this indicater is somehow relevant?

I already had feared before that this indicator might not been covered simply by the font color.

From my side i try to contribute by searching for more info if/how this indicator might be accessed (Notify step et.al).
Hopefully we find something, then this chapter could be finished.

Hm. In the Notepad++ in dark mode explorer plugin the listview header is black too,, chagnes to non-black at mouseover.
Excatly as we had April 7th. So it doesn't make sense to look into their (C++) sources here.

npp_dark_lv_header

Hm again. Explorer++ (sources for dark mode available) does behave exactly like Notepad++/dark = our version April 07. Header black, non-black at mouseover. Again it doesn't make sense to look into their sources here :-(

explorerplusplus_dark_lv_header

And unfortunately it is (at least nearly) the same with the Windows Explorer (setting dark mode for apps). Same as NPP, Explorer++ and the version april ß7.
I'm a bit disappointed because i did hope for more as information source.
WinExplorer_dark_lv_header

Our version April 07 ('normal', mouseover):

version_1pr_07

Honestly, i wouldn't have expected this coincidence. But as i saw it, i'd really near by to say: version april 07 was more appropriate in this respect. Or which conclusion to draw?

I try to summarize my impressions so far.The newly established bg color looks better, no doubt.
On the other hand: for some people the sort symbol might be irrelevant, but for others not. So i'm convinced it should be possible to show it anyway.

Digging in the net for me show no obvious hooks for to control this symbol, i didn't find a way to access it, other than to ownerdraw the header from the scratch (i assume nobody wants this. Why such effort? A graphic construct would be needed to paint, assuming, sort direction and the columns where it must be applied are known here).
Some equivalent to trigger (in CDDS_ITEMPREPAINT) something like a directive "CDRF_NEWPEN" (for a SetDCPenColor), analogous to CDRF_NEWFONT, cannot be seen.

I think it must have a reason why apparently most apps that are showing the sort symbol (if not using a bitmap for it) appear to be based on theme element "ItemsView::header". And this windows theme element is painting black background for the header, as well as showing the sort symbol.
There are also calls available to get and set theme attributes, but concise infos about that are so rare and foggy that i did not gain the impresson that it is possible to override a certain theme attribute like a bg color.

So the best imo is, in sum, to stay at the black bg with available sort direction symbols.
I just updated my local copy (based on apr. 07) so far that it becomes obvious where the difference between the two flavours is spent. A simple 'exit' could decide:

class function TWin32WSCustomListViewDark.CreateHandle(
  const AWinControl: TWinControl; const AParams: TCreateParams): HWND;
var P: TCreateParams; HeaderHWND:HWND;
begin
  P:= AParams;
  P.ExStyle:= P.ExStyle and not WS_EX_CLIENTEDGE;
  TCustomListView(AWinControl).BorderStyle:= bsNone;
  Result:= inherited CreateHandle(AWinControl, P);
  SetWindowSubclass(Result, @ListViewWindowProc, ID_SUB_LISTVIEW, 0);
  EnableDarkStyle(Result);

// exit;  // <--  Exit here if you want to have the nice bg, but without sort indicators

  HeaderHWND:=HWND(SendMessage(Result,LVM_GETHEADER,0,0));
  AllowDarkModeForWindow(HeaderHWND, True);
  SetWindowTheme(HeaderHWND,'ItemsView', nil);
  //SendMessageW(HeaderHWND, WM_THEMECHANGED, 0, 0); 
end;

==> Conclusion: i think at least this should be existent and transparent within the code. Offered via IFDEF? Per controlling variable? Commented out with a short one-liner explanation? Doesn't matter.
Offer the choice!.
Unless there are better news.

@zamtmn: i'd be really very interested in to know how do you see that.
What's your opinion about how / in which direction it might proceed?

I will draw the sorting symbol by myself. System headers doesn't suit me with their dark appearance. Unfortunately, I can't devote enough time to the project yet, everything has been postponed for later - two weeks. But you can give patches and requests, I will accept them

Ok, thanks for the info! Of course it's an understandable approach. And probably no other way if the black is not wanted (it appears to be deep inside the theme; one can inspect it's properties with the tool “msstyleEditor").

Personally for me i'd rather avoid such efforts, but to iapply the icon would be no mystery
(one needs to retrieve a/the bitmap or character or draw the chevron; needs to know when (and when not: unsorted lists) it should be shown; needs to know the affected column; needs to remember and reverse the sort direction. And: to react on column click without impacting an app itself. Maybe via a helper method).

The following articles / snippets are hopefully a bit of help:
https://stackoverflow.com/questions/32815474/sorting-listview-columns-with-arrows
https://stackoverflow.com/questions/70594957/problem-with-sort-arrow-handling-in-tlistview
https://stackoverflow.com/questions/14792244/how-to-show-the-sort-arrow-on-a-tlistview-column?rq=1
http://www.delphigroups.info/2/8c/297452.html

For the reasons mentioned i didn't see a real need to pursue this topic further and simply had used "my version"
(darker header, but having sort indicators).
But sometimes i thought about it. And now got aware of the PartId "HP_HEADERSORTARROW".
Interested, i did a test and, voila, i think there may be a quite elegant solution.
Where one even don't need to determine "what is the sort column, and what is the sort direction" for to paint the shape manually.

uwin32widgetsetdark.pas, function DrawThemeBackgroundDark:

    if (iPartId = HP_HEADERSORTARROW) then begin  // Luckily, this applies to the correct sort column :-)
      LCanvas:= TCanvas.Create;
      try
        LCanvas.Handle:= hdc;
        LCanvas.Pen.Color:=RGBToColor(192, 192, 192);   // clSilver.  Shouldn't be darker imo!
        if  iStateId = 1 then begin;    // -==== Luckily, iStateId transports the SortDirection  :-)
            LCanvas.Line(pRect.Left+3, 4, pRect.Left+7, 0);
            LCanvas.Line(pRect.Left+6, 1, pRect.Left+10, 5);
        end;
        if  iStateId = 2 then begin;    // iStateId seem to mimic SortDirection
            LCanvas.Line(pRect.Left+3, 1, pRect.Left+7, 5);
            LCanvas.Line(pRect.Left+6, 4, pRect.Left+10, 0);
        end;
      finally
        LCanvas.Handle:= 0;
        LCanvas.Free;
      end;
    end else

Attached a small test project. It uses my slighly modified dark mode files inside (subdirectory),
So for to test within your environment, simply remove the include path "DarkMode" from the project options.

Search for "CHECKME" (two places within uwin32widgetsetdark) for to see the changes i did for this topic from my side resp. for to compare the both versions (old/new).

What do you think?
If you accept this, i could prepare a merge request.
_test_ListView_Header_Darkmode_SortIndicator.zip

Remark about your painting routine: a last region within the header which is not occupied by a column stays unpainted.
Is this by intention, or should this be corrected (how)?
sortindicator

I know now how to fill the unpainted area (it's via 'if (iPartId = 0').
But there is no optical distinction (yet) from the righmost column (here column2).
I'm still unsure if this is good or bad.
sortindicator_2

... so i made this area a bit darker. By that there is a distinctive difference, but not a big one.

sortindicator_3

Modified test project: / proposal

_test_ListView_Header_Darkmode_SortIndicator_2.zip

Thanks!