2

I want to save the original PNG/BMP (32 bit with alpha) of the theme part with a specific state using GetThemeStream function.
It works well for DWMWINDOW parts as described here: GetThemeStream usage

But I'm unable to get other theme parts other than DWMWINDOW.
The OpenThemeData(0, 'BUTTON') is OK, but the call to GetThemeStream fails:

It always returns HResult -2147023728 ($80070490) : element not found.

function SaveTheme(const APathToSave: string): Boolean;
const
  ThemeRegPath = 'SOFTWARE\Microsoft\Windows\CurrentVersion\ThemeManager';
var
  hTh: HTHEME;
  hLib: HMODULE;
  DllName, Path: string;
  MS: TMemoryStream;
  BufSize: Cardinal;
  PBuf: Pointer;
  hr: HResult;
begin
  Result := False;
  { hTh := OpenThemeData(0, 'DWMWINDOW'); } // <- this works OK
  hTh := OpenThemeData(0, 'BUTTON');
  if hTh <> 0 then
  try
    // Get Library path
    SetLength(DllName, 1024);
    SHRegGetPath(HKEY_CURRENT_USER, PChar(ThemeRegPath), 'DllName', PChar(DllName), 0);
    // Open Library
    hLib := LoadLibraryEx(PChar(DllName), 0, LOAD_LIBRARY_AS_DATAFILE);
    if hLib > 0 then
    try
      hr := GetThemeStream(hTh, BP_PUSHBUTTON, PBS_NORMAL, TMT_DISKSTREAM, PBuf, BufSize, hLib);
      if hr = S_OK then begin
        MS := TMemoryStream.Create;
        try
          MS.WriteBuffer(PByteArray(PBuf)^[0], BufSize);
          MS.Position := 0;
          MS.SaveToFile(APathToSave);
          Result := True;
        finally
          MS.Free;
        end;
      end;
    finally
      FreeLibrary(hLib);
    end;
  finally
    CloseThemeData(hTh);
  end;
end;

Q: How can I save a BUTTON (BP_PUSHBUTTON) part with a state of PBS_NORMAL into a PNG using GetThemeStream?

The documentation is very poor and there are any examples on the web. I made a great effort to find some leads on how to use this functions, but I was unable to find anything useful.

zig
  • 4,524
  • 1
  • 24
  • 68
  • 3
    `GetThemeStream()` does not use `GetLastError()` to report errors. It returns an `HRESULT`, which is the actual error code, where 0 means success. So what value does it actually return when no stream is provided? – Remy Lebeau Nov 25 '17 at 17:13
  • @RemyLebeau, it always returns -2147023728 ($80070490) - element not found. I have made an edit. – zig Nov 26 '17 at 06:45
  • 1
    then there is nothing you can do. The stream you want doesn't exist – Remy Lebeau Nov 26 '17 at 07:15
  • @RemyLebeau, I think you are correct. there nothing much could be done with this API. – zig Nov 29 '17 at 07:02
  • Yes, you can do that using my answer on my own question here: [https://stackoverflow.com/questions/34222021/getthemestream-usage](https://stackoverflow.com/questions/34222021/getthemestream-usage) – Alex Egorov Dec 07 '17 at 13:45
  • @AlexEgorov, I already tested your answer. it does not work for 'BUTON' (or other parts). only works with `DWMWINDOW`. If you you can make it work with a `BUTTON` part, please post an answer and I'll upvote and accept! – zig Dec 07 '17 at 14:48
  • You are right! After some investigations I found that theme stream doesn't contain such data. – Alex Egorov Dec 13 '17 at 13:45

1 Answers1

1

After a bit more digging, I think @RemyLebeau was right and there is nothing I can do with GetThemeStream. specially since the documentation is a joke.

The only thing that "works" is GetThemeBitmap. which is also a mystery in itself. it disregards the part State and the output bitmap contains all the available states.

enter image description here

See also: How to get an icon associated with Windows theme?

zig
  • 4,524
  • 1
  • 24
  • 68