NO

Author Topic: Enable Dark Mode for Title bar  (Read 14497 times)

Offline WiiLF23

  • Member
  • *
  • Posts: 89
Re: Enable Dark Mode for Title bar
« Reply #30 on: February 05, 2024, 10:46:28 PM »
Hey John Z. It would appear to me that MS may of removed the API exposure for modifying the scrolling bar in order to divert the choices toward the unofficial dark mode visual theme string "Darkmode_Explorer".

I bet you can do this in .NET 7 on Windows 10 easily. I'll never touch Windows 11, or their VS stack again.

That is good info too, that would take a bit of time to discover - thank you for that bit.

Offline John Z

  • Member
  • *
  • Posts: 860
Re: Enable Dark Mode for Title bar
« Reply #31 on: February 05, 2024, 10:58:06 PM »
Hi WiiLF23,

I located a possible solution:
"Replace a Window's Internal Scrollbar with a customdraw scrollbar Control"
over on CodeProject :
https://www.codeproject.com/Articles/14724/Replace-a-Window-s-Internal-Scrollbar-with-a-custo

Sounds reasonable -

I've not tried it yet.

John Z

Offline WiiLF23

  • Member
  • *
  • Posts: 89
Re: Enable Dark Mode for Title bar
« Reply #32 on: February 09, 2024, 04:37:34 AM »
Hi John Z,
That's interesting! I wonder how many editions that is supported on (notably Windows 10). I've never seen something like that before - very cool!


Offline John Z

  • Member
  • *
  • Posts: 860
Re: Enable Dark Mode for Title bar
« Reply #33 on: February 09, 2024, 08:34:50 PM »
Hi WiiLF23,

Yup, out-of-the-box thinking, sometimes neat results occur, sometimes disaster  ;)

Custom caret for 'manual' dark mode is working well I'll post a bit more about it later.
Nothing earthshaking relatively straightforward, certainly no OOB thinking.....


John Z

Offline John Z

  • Member
  • *
  • Posts: 860
Re: Enable Dark Mode for Title bar
« Reply #34 on: February 09, 2024, 10:27:39 PM »
Custom Caret for Dark Mode (sorry a little long...)

Turns out it is not too difficult.  There are a few point to clear up however.

The color of the caret is not going to be the color of the bitmap replacement.
It is some combination of the background and bitmap colors.  Somewhere I read only
white bits are inverted. For example with a certain gray background a brown bitmap
gives a green caret change background the caret is red with same bitmap...See attachments

The bitmap caret is not automatically scaled with the font height. To look best
this would require building the caret bitmap in code on the fly after a font change
rather then using a predefined bit map.  Still considering if worth it...

I'm using accelerator keys in the program so my main windows is created with
hwndMain= CreateDialog(hInstance, MAKEINTRESOURCE(DLG_MAIN),....
so that I can have TranslateAccelerator in the actual msg loop

IN/On the main window are edit boxes.  for example
  CONTROL "Middle", Text2, "Edit", ES_AUTOHSCROLL|WS_TABSTOP, 188, 72, 104, 12, WS_EX_STATICEDGE, 202

These controls are the ones needing the custom caret when in DarkMode

In main MainDlgProc I check the msg for what has current focus if one of the edit controls has it and it was not also the last control to have focus then I set the caret to the control.  SO far so good everything appears to work as expected.  If not in Dark Mode skip unless 1st transition out of DarkMode then set caret back to system original.

My concern is that - 
MS says "The system provides one caret per queue. A window should create a caret only when it has the keyboard focus or is active. The window should destroy the caret before losing the keyboard focus or becoming inactive."
A new caret will always destroy the old one

If further says "the windows will be sent WM_KILLFOCUS before the actual focus is lost so that DestroyCaret(); can be used.  The edit box child windows never send this message when they lose focus.  It does appear that they automatically destroy my caret when leaving because the next time I go there I still need to set the caret to the new one even though I did it before.

I did add DestroyCaret to the CLOSE message routine for the main window just in case.
Did a lot of testing jumping to different programs and within my own everything appears to be ok but I'm not sure I'm not missing something....

Code: [Select]
/-----------------------------------------------------------------------
// Function : Set_one_Caret
// Task : Set the dark mode edit caret cursor to usable color
//              : and set it back to the std caret as required
// Note     :
// Input : context on state TRUE = Dark Mode caret, FALSE = Std
//-----------------------------------------------------------------------
void Set_one_Caret( BOOL context_on, HANDLE hwnd)
{ int ans;
  static HANDLE last_hwnd=NULL;
  static BOOL last_context=FALSE;
  DWORD err;
  RECT cwin;
  int h=0;

  if ((last_hwnd == hwnd) && (last_context == context_on))
{ return;}

    // NOT really needed just for testing
GetClientRect(text[0].hctl,&cwin);// sizes std caret to control window
    h = cwin.bottom-cwin.top-2;       // only useful for built in caret

    HBITMAP hCaret1=NULL;// caret bitmap handles
if (context_on)
  { hCaret1 = LoadBitmap(ghInstance,MAKEINTRESOURCE(CARET_W));
if (hCaret1 == NULL)
           MessageBoxA(NULL,"Failed load bitmap","Set_One_Caret",MB_OK);
     // no crash with NULL though just uses system caret - so ok fall through
        ans = CreateCaret(hwnd,hCaret1,0,h);   // new cursor, h ignored
err = GetLastError();
if (ans == 0)
{MessageBoxA(NULL,"Failed Create New","Set_one_Caret",MB_OK);
             Show_Error(err, L"Set_one_Caret- creating"); //error display
    }
ans = ShowCaret(hwnd);
err = GetLastError();
if (ans == 0)
  { MessageBoxA(NULL,"Failed Show New","Set_one_Caret",MB_OK);
            Show_Error(err, L"Set_one_Caret- show"); //error display
  }
      }

   else //revert to system caret
{ // test use edit box height (h) to the set system caret height - Works
ans = CreateCaret(hwnd,(HBITMAP) 1,2,h);   // std Caret
        err = GetLastError();
if (ans == FALSE)
   {MessageBoxA(NULL,"Failed Re-Create Old","Set_one_Caret",MB_OK);
            Show_Error(err, L"Set_one_Caret- Reset,Create"); //error display
   }
ans = ShowCaret(hwnd);
        err = GetLastError();
if (ans == FALSE)
  { MessageBoxA(NULL,"Failed Re-Show Old","Set_one_Caret",MB_OK);
            Show_Error(err, L"Set_one_Caret- Reset,Apply"); //error display
  }
}

last_hwnd = hwnd;
last_context = context_on;

return;

}/* end set_one_caret */





John Z
« Last Edit: February 11, 2024, 03:45:22 AM by John Z »

Offline WiiLF23

  • Member
  • *
  • Posts: 89
Re: Enable Dark Mode for Title bar
« Reply #35 on: February 29, 2024, 09:00:19 PM »
Looking good John Z.

I've been off the map for a bit (literally), and I am very thankful I produced the app to accommodate mass interruption. This leaves me with 1 foot in the door and the other pending for an undetermined timeframe.

I guess this is time to dig even deeper in C programming, and provide what I learn and prove possible.

I know it is not the end. I just have massive hopes and dreams, and it is hard for one person to pull it off on this scale.

Wish me luck!

Offline Ushavilash

  • Member
  • *
  • Posts: 5
Re: Enable Dark Mode for Title bar
« Reply #36 on: April 10, 2024, 10:36:20 AM »
Thanks for sharing that information and resources that is really helpful.

Offline WiiLF23

  • Member
  • *
  • Posts: 89
Re: Enable Dark Mode for Title bar
« Reply #37 on: April 11, 2024, 11:28:20 PM »
You are most welcome! I will revisit this in coming weeks for additions and improvements.

TreeView painting procedure should be implemented into dark mode as well, as many people including myself rely on TreeView for data.

I completed the painting 2 months back, but I didn't post about it. I'll add the addition of this code, as well as a custom splash screen making full use of control designing.

« Last Edit: April 11, 2024, 11:43:23 PM by WiiLF23 »

Offline John Z

  • Member
  • *
  • Posts: 860
Re: Enable Dark Mode for Title bar
« Reply #38 on: April 12, 2024, 12:22:05 PM »
TreeView color fallback is also easy to do if one wants to supplement or avoid using window theme methods, which my Dark Mode mostly does.

Here is a code snippet:
Code: [Select]
case WM_CTLCOLORLISTBOX:
case WM_CTLCOLOREDIT:

//BookMark [{treeview color}]
        if ((HWND)lParam == GetDlgItem(gHWND, TreeView1))
  { if ((StartUp.ThemeAll == TRUE))// && (StartUp.ThemeNum >0))
      {// could color here too
TreeView_SetBkColor(GetDlgItem(gHWND, TreeView1),gColor);
                TreeView_SetTextColor(GetDlgItem(gHWND, TreeView1),lColor);
                return TRUE;
      }
    else
      {// back to 'normal'
TreeView_SetBkColor(GetDlgItem(gHWND, TreeView1),RGB(255,255,255));
                TreeView_SetTextColor(GetDlgItem(gHWND, TreeView1),0);
                return TRUE;
      }
           }

The advantage is that one can color it anyway desired.  Both background and font can be colored.

John Z