views:

227

answers:

3

I have a Delphi 2010 app which shows/hides the desktop icons under XP fine. However under my Window 7 test environment (happens to be 64 bit) the icons don't disappear.

Here is the critical code I am using (for the hide):

ShowWindow(FindWindow(nil, 'Program Manager'), SW_HIDE );

I have found I can set the registry:

[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced]
"HideIcons"=dword:00000001

And that works fine if I restart windows (or kill explorer and restart it), however is there a way to get the old code to work and/or tell the desktop to reload using the new registry information without such radical methods.

Thank in advance.

A: 

Use 'ProgMan' instead of 'Program Manager'.
Works in Win 7 32 bits (don't have my 64 bits available here).

procedure ShowDesktopIcons(const Visible: Boolean);
var
  h: THandle;
begin
  h := FindWindow('ProgMan', nil);
  if h = 0 then
    RaiseLastOSError;
  if Visible then
    ShowWindow(h, SW_SHOW)
  else
    ShowWindow(h, SW_HIDE);
end;

procedure TForm1.btnHideClick(Sender: TObject);
begin
  ShowDesktopIcons(False);
end;

procedure TForm1.btnShowClick(Sender: TObject);
begin
  ShowDesktopIcons(True);
end;
François
This does not work under Windows 7 64-bit.
Andreas Rejbrand
Do not use hacks
Alexander
+4  A: 

Use SHGetSetSettings function. You're interested in fHideIcons field and corresponding SSF_HIDEICONS flag.

Alternatively, you can use corresponding group policy.

Alexander
This seems like the nice way to do it, indeed.
Andreas Rejbrand
@Alexander, if you have made this work you could also answer http://stackoverflow.com/questions/3326062/how-do-i-make-the-show-hide-desktop-icons-setting-take-effect
Sertac Akyuz
I'm **not** an expert in this field - I just do a quick googling. *That took 1 minute of my time*. I've posted answer to your specified question as well - by the same approach. P.S. Seriosly, I do not understand why any "RTFM" answer is down-voted here, on StackOverflow (even if it has link on google search term). You'll get **MUCH** better results by googling official docs for approved solution, than using hacks (registry read/write, window manipulations, etc) from answers.
Alexander
@Alexander - I haven't down voted anything and I don't see a down-vote on your answer. But I can see reason; if the RTFM answer does not actually work... The question I referred is not mine, I figured if you've actually used the approach you could help the guy, no offense intended!
Sertac Akyuz
Alexander, thanks greatly for pointing in this direction, it totally escaped my search (sometimes its not a issue of RTFM but just can't figure out the index of the FM ;-). However I have yet to get a working SHGetSetSettings test program to work with XP or Win7 64 bit. There seems to be very few Delphi examples using this routine and while they seem to compile and run, they do nothing. Perhaps the Delphi ShellAPI or ShlObj libraries (which I am using) have errors. Will keep trying, because this does seem to be the 'official' way.
lgallion
@Sertac No, I didn't mean you or anyone else personally, I just wondered what's wrong with this world - that's all.
Alexander
@lgallion Actually it works on Win7 x64. It just don't refresh desktop - that's all. You can see it by right clicking on desktop and verifying "Show icons" options. You need to find a way to refresh desktop after this change.
Alexander
@Alexander - Yeah, I also sometimes notice down-votes are not scarce. For instance I don't understand the down-vote on François' answer since he is not answering *how to hide desktop icons*, he is answering a specific question on why some code piece does not work; he is not expected to present alternatives. Besides, he also deliberately mentions that he has no way of testing the code on 64bit. Well, maybe I'm missing sth...
Sertac Akyuz
A: 

Ok, here is the revised hackish method (sorry Alexander!):

var
DeskHandle : HWND;

...

///////////////////////////////////////////////////////////////////////
// Callback function for EnumWindows
///////////////////////////////////////////////////////////////////////
function MyGetWindow (Handle: HWND; NotUsed: longint): bool; stdcall;
var
  hChild : HWND;
begin
  if handle <> 0 then
  begin
    hChild := FindWindowEx(handle, 0, 'SHELLDLL_DefView' ,nil);
    if hChild <> 0 then
    begin
      hChild := FindWindowEx(hChild, 0, 'SysListView32' ,nil);
      if hChild <> 0 then
      begin
        DeskHandle := hChild;
      end;
    end;
  end;
  result := TRUE;
end;

procedure ShowDesktopIcons(const Show : boolean) ;
begin
  DeskHandle := 0;
  EnumWindows(@MyGetWindow, 0);

  if DeskHandle <> 0 then
  begin
    if Show then
    begin
      ShowWindow(DeskHandle, SW_SHOW );
    end
    else
    begin
      ShowWindow(DeskHandle, SW_HIDE );
    end;
  end;
end;

The issue arises because parent/child relationship between "Progman" and SysListView32 has changed from XP to Vista/Win7 (precisely why you shouldn't use a hack ;-). In addition, applying a theme with multiple pictures under Win7 (my test environment) changes this relationship even further. Therefore the new routine looks through all windows until it finds one with a "SHELLDLL_DefView" and "SysListView32" child set under one. It then returns the handle of SysListView32 in the global variable DeskHandle. Not elegant, not sure to work in future code, but works today.

If anyone can get a SHGetSetSettings version to work, that is definitely the correct way to go, not this junk.

lgallion
I notice no effect on Windows 7 64-bit when compiled with Delphi 2009.
Andreas Rejbrand
Andreas, you are correct, it only works in some situations. The problem is with themes. I went to a Windows 7 Basic theme for another reason and the code worked. I attributed it to the code, not the theme change (oops!).
lgallion
The problem is once again the location of "Progman" window. With Win 7 default theme the structure looks like this:"->SysListView32->SHELLDLL_DEFView->Progman"With a theme:"->SysLIstView32->SHELLDLL_DefView->WorkerW->WorkerW->Progman"I am trying to put together Delphi 2010 code to get Progman no matter how deep it is nested (different themes may create a different number of WorkerW (or other type) of Windows in the stack. Any help would be appreciated so I can correct the answer.
lgallion
The revised code above should work with Win 7 and themes with multiple pictures, as well as other XP to Win 7 environments.
lgallion