Recent

Author Topic: Dark Theme in my program?  (Read 5434 times)

zamtmn

  • Hero Member
  • *****
  • Posts: 560
Re: Dark Theme in my program?
« Reply #30 on: March 31, 2023, 11:13:21 pm »
An excellent and long-awaited solution.
I will use this in my projects. It would be great if the author designed this as a separate package.
But while it's not there, I've done it https://github.com/zamtmn/metadarkstyle I made small changes so that it was easy to use and did not interfere with compilation in Linux

alex2000, please make it a separate package. Thanks!!!

domasz

  • Full Member
  • ***
  • Posts: 224
Re: Dark Theme in my program?
« Reply #31 on: March 31, 2023, 11:17:00 pm »
Maybe we should post it to github.com/doublecmd
Set up your own Github, give a name to this project and post it there so it can be used with other Lazarus projects easily.

d7_2_laz

  • Sr. Member
  • ****
  • Posts: 362
Re: Dark Theme in my program?
« Reply #32 on: April 01, 2023, 09:27:43 am »
A dedicated place for this excellent tool would be really nice indeed. Every time i post within this specific thread i've a bad feeling, as it's no Lazarus topic in the strict sense and somebody might be bothered by off-topic stuff.

Hi Erik, great approach!   :)
Ah, i see the difference (actually looking onto the listview). Apparently there might be reasons to take a separate header control (for me that would impact existing stuff too much).
For an 'esisting' header the background brush is dimmed down, so that the black font keeps somehow to be readable.
That's surely a possible solution - better anyway than empty black bars  8-)  - and suitable for many projects   :)

But the sort indicator - if set - goes lost, will visually disappear, bad  :o
For that reason i'd rather stay at the 'ItemsView::Header' approach if the text color only could be changed.
If there's now already a 'TWin32WSCustomListViewDark' intoduced, probably an own subclassed windowproc will be needed, i fear.
One reason i hoped to avoid this is that it possibly might interfere with a component's own builtin listview subclassing. But i don't know yet. Proabably there's no way around (the subclass shouldn't touch the default windowproc unless notifications reagarding the header's text color is referred to).

Regarding Double Commander, it should be taken into account that it doesn't use a listview, so this is not in their scope.

My main and only concerns at that stage would be:
- (Needed:) good readable listview's column headers -> without loosing a sort indicator
- (Liked:) app-wise controlling dark on/off (eg. via an ini key). This is still a bit unfocused. Erik, I think, that would be needed for you IDE problem too.
 Actually i'm using IFDEFs (using a file 'set_USE_DARKMODE.INC' for to switch). Results in to exe's; light, dark. There should be a better way.
  @zamtmn, do your files already handle this eg. via udarkstyleparams.pas?
« Last Edit: April 01, 2023, 10:54:06 am by d7_2_laz »

zamtmn

  • Hero Member
  • *****
  • Posts: 560
Re: Dark Theme in my program?
« Reply #33 on: April 01, 2023, 11:55:24 am »
I haven't delved into the rendering problems yet. The control of turning on / off the dark theme is at the initialization stage of the application. I have added usage examples

d7_2_laz

  • Sr. Member
  • ****
  • Posts: 362
Re: Dark Theme in my program?
« Reply #34 on: April 01, 2023, 10:21:22 pm »
After a lot of attempts finally i could succeed (happy).  :)
-> ListView column header font color white; sort indicator is preserved.

The key is: Listview subclass; WM_NOTIFY;  when NMHdr^.code = NM_CUSTOMDRAW : when dwDrawStage is CDDS_ITEMPREPAINT  ==> SetTextColor(NMCustomDraw^.hdc , SysColor[COLOR_HIGHLIGHTTEXT]);

(It doesn't work in my app yet. Maybe two subclassings of the listview are mutual exlusive. I'll see. But the principle is shown).

zamtmn; I look forward to seeing your examples

zamtmn

  • Hero Member
  • *****
  • Posts: 560
Re: Dark Theme in my program?
« Reply #35 on: April 02, 2023, 07:26:51 am »
Examples are already there. But I repeat, this is just making someone else's code into a package for easy use

d7_2_laz

  • Sr. Member
  • ****
  • Posts: 362
Re: Dark Theme in my program?
« Reply #36 on: April 02, 2023, 05:26:23 pm »
"Examples are already there"  .. Yes, but 'seeing' meant inspecting, not searching for ... Sorry for my misunderstandable wording here zamtmn!

Saw now why it (partially) doesn't work in the app.
For listview objects created 'in the background' during the CormCreate, in the subclass the WM_NOTIFY, customdraw resp, the draw stages CDDS_PREPAINT and CDDS_ITEMPREPAINT won't be called.
'In the background' does mean: imagine objects that are assigned to pagecontrol tabs where only one is active/visible.
For new created tabs with it's objects it will work immediately.

For to draw a conclusion: it's needed to call (for listview header) WM_NOTIFY with the draw stage information programatically.
But how? After more than ten diverse attempts i went stuck.

Maybe somebody had a similar problem and knows a solution:  how to kick the WM_NOTIFY processing including it's parameters correctly?

Wanted to be called from outside:

Code: Pascal  [Select][+][-]
  1. function ListVieWindowProcSubclassed(Window: HWND; Msg: UINT; wParam: Windows.WPARAM; lParam: Windows.LPARAM; uISubClass: UINT_PTR; dwRefData: DWORD_PTR): LRESULT; stdcall;
  2. var NMHdr: PNMHDR; NMCustomDraw: PNMCustomDraw;
  3. begin
  4.     If Msg = WM_NOTIFY then begin
  5.        NMHdr := PNMHDR(LParam);
  6.        if NMHdr^.code = NM_CUSTOMDRAW then begin
  7.           NMCustomDraw:= PNMCustomDraw(LParam);
  8.           case NMCustomDraw^.dwDrawStage of
  9.             CDDS_PREPAINT:
  10.              begin
  11.                Result := CDRF_NOTIFYITEMDRAW;
  12.                exit;
  13.              end;
  14.             CDDS_ITEMPREPAINT:
  15.              begin
  16.                SetTextColor(NMCustomDraw^.hdc , SysColor[COLOR_HIGHLIGHTTEXT]);
  17.                Result := CDRF_NEWFONT;
  18.                exit;
  19.              end;
  20.           end;
  21.         end;
  22.     end;
  23.     Result := DefSubclassProc(Window, Msg, WParam, LParam);
  24. end;


zamtmn

  • Hero Member
  • *****
  • Posts: 560
Re: Dark Theme in my program?
« Reply #37 on: April 02, 2023, 11:04:06 pm »
« Last Edit: April 03, 2023, 02:58:49 am by zamtmn »

zamtmn

  • Hero Member
  • *****
  • Posts: 560
Re: Dark Theme in my program?
« Reply #38 on: April 03, 2023, 09:35:36 am »
I create TWin32WSCustomListViewDark and add your code https://github.com/zamtmn/metadarkstyle/commit/7941bcda7931e403ef707bf892932b9e89fcf32f

You can draw a dark title here. But pay attention, this file is not included in the list of the package files for compilation in linux, therefore, after editing it, in order for the changes to take effect, you need to erase the metadarkstyle\lib folder

d7_2_laz

  • Sr. Member
  • ****
  • Posts: 362
Re: Dark Theme in my program?
« Reply #39 on: April 03, 2023, 11:19:26 am »
Thank you zamtmn, appreciated!  :)

But without those adapten lines in InterceptOpenThemeData (as of the sample project file in reply #34)
it won't have the desired effect for changing the font color of the header (or do you see it anyway?)
Code: Pascal  [Select][+][-]
  1.   // within InterceptOpenThemeData
  2.   else if lstrcmpiW(pszClassList, 'ListView') = 0 then
  3.   begin
  4.      hColHdr := Listview_GetHeader(hwnd);   // Listview_GetHeader:in CommCtrl. // hColHdr: HWND; <- define it at the beginning of the function
  5.      if hColHdr <> 0 then begin
  6.        AllowDarkModeForWindow(hColHdr, True);
  7.        pszClassList:= PWideChar('ItemsView::Header');
  8.        SetWindowTheme(hColHdr, 'ItemsView', NIL); // Please note that the ListView itself stays intentionally at theme 'DarkMode_Explorer'
  9.        SendMessageW(hColHdr, WM_THEMECHANGED, 0, 0);
  10.      end;
  11.   end
  12.  

For me this works fine together with my listview component within my app
- when placing it "standalone" in a Mainform
- or when adding tabs (-> each containing a listview) when the MainForm is already open.
There's only a problem when adding tabs triggedred within the FormCreate (the Notify does not pass NM_CUSTOMDRAW here).

I suspect something special on my own side, not the modified uwin32widgetsetdark.pas.
So the patch you mentioed (tried it) does not have an effect here (expectedly).
If i should find something special having a common interest regarding the dark theme files, i'll come back here later.

zamtmn

  • Hero Member
  • *****
  • Posts: 560
Re: Dark Theme in my program?
« Reply #40 on: April 03, 2023, 01:20:35 pm »
here is the result, not bad and not good ((

d7_2_laz

  • Sr. Member
  • ****
  • Posts: 362
Re: Dark Theme in my program?
« Reply #41 on: April 03, 2023, 01:48:57 pm »
Regarding the listview?
I think the column header seems good (your image).
There's here a selected-color (line "By layer") that does not look find, but i think that's a different topic to focus on.
- in the mini test project i had "RowSelect" true and no specifc ownerdraw
- in the app, where i use ownerdraw extensively, that one had to be adapted a bit anyway., But actually it would look like (attached image: item selected;  item edited).
I had already noticed that "edited" had not fully covered yet and could be a specific topc.
But the column header is fine, right?

d7_2_laz

  • Sr. Member
  • ****
  • Posts: 362
Re: Dark Theme in my program?
« Reply #42 on: April 04, 2023, 10:46:56 am »
Found the problem why it stucked im my app. Had nothing to do do with the changes mentioned in the last conversations.
No more doubts regarding the listview column header font coloring now. The uwin32widgetsetdark.pas as contained in the attachment in reply #34 works fully fine for this.

Erik, zamtmn, now I have more concentration to try your changes.
Lazarus is excellent, and this little addon is an excellent on-top capability as well  :)

d7_2_laz

  • Sr. Member
  • ****
  • Posts: 362
Re: Dark Theme in my program?
« Reply #43 on: April 07, 2023, 11:24:15 am »
Worked with the modified version, appears still fine, except one little observation. Not drastic, but a bit annoying. Category: nice if it wouldn't happen.
After populating a treeview contained by a panel, one sees a white flashing for a short time (background repaint with white brush).
I do see this mainly on the left aligned panel (independently where each the focus is).

Already tried a couple of known measures (*), but, for to shorten this, i think it can be shown by a short test project (using shelltreeviews (those are examples only) on panels.
Maybe somebody likes this addon like me and already encountered an additional technique what possibly might intercept that.

Puzzle: why the 'white flashing' is much more noticeable at the left panel than at the right panel?  // has nothing to do with the caching of file objeccts
Why can't the left treeview not behave like the right treeview?

(*) keywords: DoubleBuffered; ParentBackground; WM_SETREDRAW; LockWindowUpdate; SetClassLongPtrW(<aHandle>,GCL_HBRBACKGROUND,<aColor>); Disable/Enable Align; intercept WM_ERASEBKGND et. al.

d7_2_laz

  • Sr. Member
  • ****
  • Posts: 362
Re: Dark Theme in my program?
« Reply #44 on: April 08, 2023, 11:12:21 am »
After various attempts i came back to the SetClassLongPtrW(<aHandle>, GCL_HBRBACKGROUND,<aColorIdex>)   (*)
Within a proper arrangement of properties involved indeed it appears to me as a solution.
At least far far better than a white flash on dark background  :P
And btw (i didn't mention that yet) the control's background does behave far better than before when maximizing the form (no more artefacts here) .
  :)
Fixed version attached.

/*) Amongst the 25 possible color indices, the following are applicable to try:
 24 (COLOR_INFOBK)  19 (COLOR_INACTIVECAPTIONTEXT)  10 (COLOR_ACTIVEBORDER) 2 (COLOR_ACTIVECAPTION)  8 (COLOR_WINDOWTEXT)  9 (COLOR_CAPTIONTEXT)  10 (COLOR_BTNSHADOW)  20 (COLOR_3DHILIGHT, COLOR_BTNHIGHLIGHT, COLOR_BTNHILIGHT)
« Last Edit: April 08, 2023, 11:21:39 am by d7_2_laz »

 

TinyPortal © 2005-2018