6

I am writing a plugin for Autodesk 3ds Max, a native, Windows-only application. The plugin is written in C++ and uses the raw Win32 API to build its user interface, as 3ds Max plugins are supposed to.

I would like to display an HTML link in the plugin's UI to let the user download a new version of the plugin from the web. The SysLink control seems to do the job.

Here's the difficulty: the colors of 3ds Max's user interface are configurable. I would like my plugin to be a good citizen, so I need the SysLink control to use the same color as other static labels.

Unfortunately, right now the text of the SysLink control is always drawn in blue, which doesn't work so well with the dark color theme of 3ds Max. Moreover, it doesn't look like I can ask 3ds Max for its color palette.

How could I make the SysLink control use the same color as other static labels?

The plugin's user interface with the light theme The plugin's user interface with the dark theme

FruitBreak
  • 570
  • 1
  • 7
  • 19
François Beaune
  • 4,270
  • 7
  • 41
  • 65
  • 2
    The entire UI is styled in a bespoke manner. Windows means for controlling appearance won't help because 3ds is painting. I think that means you need to use a control that 3ds knows how to style. Looks like it doesn't recognise sys links. Switch to a control that 3ds knows about. – David Heffernan Dec 02 '15 at 08:34
  • The thing is, while the push buttons and text edit controls are custom 3ds Max controls, all the static labels are plain Windows controls. It is infuriating that the SysLink looks decent and works as expected, but is just not displayed in a readable color when using the dark theme. – François Beaune Dec 02 '15 at 09:17
  • Whilst they may be windows controls, it seems that 3ds is painting them – David Heffernan Dec 02 '15 at 10:02
  • 1
    On the other hand perhaps LIS_DEFAULTCOLOR is what you need. Then your bigger problem is that you can't find out the palette from 3ds...... they've really sold you down the river with the stupid styling. – David Heffernan Dec 02 '15 at 12:30
  • At this point I would be happy if I could change the color of the SysLink at all. Right now the parent window doesn't seem to be receiving `WM_CTLCOLORSTATIC` events. – François Beaune Dec 02 '15 at 12:59
  • It won't until you use LIS_DEFAULTCOLOR – David Heffernan Dec 02 '15 at 13:01
  • You mean like in @Barmak answer below? I've tried, unfortunately to no avail. – François Beaune Dec 02 '15 at 13:06
  • Or maybe the state has to be removed. Pass LIS_DEFAULTCOLORS for the mask and 0 for the state. I don't know. The documentation is close to useless. Perhaps it's just not possible. – David Heffernan Dec 02 '15 at 13:14
  • Doesn't seem to work any better. I guess I'll have to give up and use a plain, ugly button. Thanks anyway, appreciated! – François Beaune Dec 02 '15 at 13:19
  • Probably 3ds is already handling syslink control color, but it is doing it wrong. It is correctly changing the background color. It is also changing text color for the static part of syslink. – Barmak Shemirani Dec 02 '15 at 15:37
  • saw this because have same problem - complete blue *SysLink* text (not only url part) in dialog box. and no any 3ds here. so it unrelated. the `LIS_DEFAULTCOLORS` also unrelated here. found that this determinated by *SysLink* **style** - if exist `0xA` in style - all is blue and handle `WM_CTLCOLORSTATIC` no effect, but if reset `0xA` in style - all draw as excepted and `WM_CTLCOLORSTATIC` became effective - i can change color of not url part. the default dialog editor by some reason set `0xA` style in *.rc* file. change `A` to `0` resolve problem. or by set `GWL_STYLE` too late for your – RbMm Jul 15 '19 at 14:21

1 Answers1

5

Edit:

This is what syslink control should look like by default:

syslinkControl

Note the static part is black (same as static controls). Only the link part is blue. In your case everything is always blue, and background color matches dialog color. Therefore the application has already made custom changes.

If there is normal message handling then the code below should change everything to red:


Use WM_CTLCOLORSTATIC, but you have to tell the syslink control to accept color change:

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch(msg)
    {

    case WM_CTLCOLORSTATIC:
    {
        HDC hdc = (HDC)wp;
        SetTextColor(hdc, RGB(255, 0, 0));
        SetBkColor(hdc, GetSysColor(COLOR_BTNFACE));
        return (LRESULT)GetSysColorBrush(COLOR_BTNFACE);
    }

    case WM_INITDIALOG:
    {
        ...
        LITEM item = { 0 };
        item.iLink = 0;
        item.mask = LIF_ITEMINDEX | LIF_STATE;
        item.state = LIS_DEFAULTCOLORS;
        item.stateMask = LIS_DEFAULTCOLORS;
        SendMessage(hsyslink, LM_SETITEM, 0, (LPARAM)&item);
        ...
        return TRUE;
    }
    ...    
    }
...
}
Barmak Shemirani
  • 30,904
  • 6
  • 40
  • 77
  • Thanks for your answer. I tried your code, but my message loop is not receiving any `WM_CTLCOLORSTATIC` event, for some reason. Still investigating. – François Beaune Dec 02 '15 at 08:04
  • [According to MSDN](https://msdn.microsoft.com/en-us/library/windows/desktop/bb787524%28v=vs.85%29.aspx), `WM_CTLCOLORSTATIC` is only used for static or edit controls. Does a SysLink fall into that category? – François Beaune Dec 02 '15 at 08:33
  • *How could I make the SysLink control use the same color as other static labels?* On second thought, the static part of the syslink control should have the same color as other static controls (even if you don't make any of the changes which I suggested). The background seems to the right color. Maybe `WM_CTLCOLORSTATIC` is processed in a different place. In a simple window or dialog you should be able to catch `WM_CTLCOLORSTATIC` – Barmak Shemirani Dec 02 '15 at 09:01
  • Thanks @Barmak for the detailed answer. I *suppose* your code would work in a normal Win32 environment; unfortunately it doesn't in 3ds Max. I mark this answer as accepted since it does answer the question very well and it might help others. Thanks again. – François Beaune Dec 02 '15 at 15:43