Reputation: 109003
I just read this question and this question, and since then I have been trying to call SHGetSetSettings
in Delphi. This is a function of shell32.dll
, but is not defined in ShlObj.pas
, so we need to write our own definition.
First we need to translate the SHELLSTATE
structure. Now I have only limited experience in C, but I suppose that ": 1" means that the member of the structure is a single bit, that is, that eight of them can be packed together in a byte. I also suppose that DWORD
= UINT
= 32-bit unsigned integers and that LONG
= int
are 32-bit signed integers. But then we have a problem: The entire structure will then occupy 228 bits, or 28.5 bytes, which is ... rather impossible, at least in Delphi, where sizeof(SomeRecord)
has to be an integer.
Nevertheless, I tried to solve it by adding four dummy bits at the end. 232 bits = 29 bytes, which is nice.
Hence I tried
PShellState = ^TShellState;
TShellState = packed record
Data1: cardinal;
Data2: cardinal;
Data3: cardinal;
Data4: cardinal;
Data5: cardinal;
Data6: cardinal;
Data7: cardinal;
Data8: byte; // Actually a nibble would be sufficient
end;
and then I declared (for later convenience)
const
fShowAllObjects = 1;
fShowExtensions = 2;
fNoConfirmRecycle = 4;
fShowSysFiles = 8;
fShowCompColor = 16;
fDoubleClickInWebView = 32;
fDesktopHTML = 64;
fWin95Classic = 128;
fDontPrettyPath = 256;
fShowAttribCol = 512;
fMapNetDrvButton = 1024;
fShowInfoTip = 2048;
fHideIcons = 4096;
fWebView = 8192;
fFilter = 16384;
fShowSuperHidden = 32768;
fNoNetCrawling = 65536;
Now I felt ready to define
interface
procedure SHGetSetSettings(var ShellState: TShellState; Mask: cardinal; DoSet: boolean); stdcall;
implementation
procedure SHGetSetSettings; external shell32 name 'SHGetSetSettings';
But before I tried the code, I noticed something very strange. I found that the constants I declared were already declared here: SSF Constants. Notice that SSF_HIDEICONS = 0x00004000 = 16384 ≠ fHideIcons = 4096
. If the SSF_
constants really are masks used together with SHELLSTATE
, then it makes no sense to define SSF_HIDEICONS
as 2^14 when it is the 13th bit (and its mask should be 2^12) in the structure. Hence, it seems, the two MSDN reference pages contradict eachother.
Could someone please bring some clarity into all this?
Upvotes: 3
Views: 908
Reputation: 21640
The D2010 declaration of SHELLSTATE in ShlObj.pas is unfortunately incorrect, but the first group of bits (17) is correctly matched with Data: DWORD;
(Yours is indeed OK).
There could be 18 or 19 of them all the same. Then we should get 2 more DWORD/UINT for the 2 Win95unused, not only Data2.
Too bad because the SSF flags and SHGetSetSettings declarations are already done in there and correct.
The correct declaration according to MSDN should be IMO:
tagSHELLSTATEW = record
Data: DWORD;
{ fShowAllObjects: BOOL:1;
fShowExtensions: BOOL:1;
fNoConfirmRecycle: BOOL:1;
fShowSysFiles: BOOL:1;
fShowCompColor: BOOL:1;
fDoubleClickInWebView: BOOL:1;
fDesktopHTML: BOOL:1;
fWin95Classic: BOOL:1;
fDontPrettyPath: BOOL:1;
fShowAttribCol: BOOL:1;
fMapNetDrvBtn: BOOL:1;
fShowInfoTip: BOOL:1;
fHideIcons: BOOL:1;
fWebView: BOOL:1;
fFilter: BOOL:1;
fShowSuperHidden: BOOL:1;
fNoNetCrawling: BOOL:1;}
dwWin95Unused: DWORD;// Win95 only - no longer supported pszHiddenFileExts
uWin95Unused: UINT; // Win95 only - no longer supported cbHiddenFileExts
// Note: Not a typo! This is a persisted structure so we cannot use LPARAM
lParamSort: Integer;
iSortDirection: Integer;
version: UINT;
// new for win2k. need notUsed var to calc the right size of ie4 struct
// FIELD_OFFSET does not work on bit fields
uNotUsed: UINT;// feel free to rename and use}
Data2: DWORD;
{ fSepProcess: BOOL:1;
// new for Whistler.
fStartPanelOn: BOOL:1;
fShowStartPage: BOOL:1;
// new for Windows Vista
fAutoCheckSelect: BOOL:1;
fIconsOnly: BOOL:1;
fShowTypeOverlay: BOOL:1;
// If you need a new flag, steal a bit from from fSpareFlags.
// Also, keep SHELLFLAGSTATE and SHGetSettings in sync when adding new flags.
fSpareFlag: UINT:13;}
end;
You can verify that this allows to get the sorting properties correctly with:
var
lpss: tagSHELLSTATEW;
begin
ZeroMemory(@lpss, SizeOf(lpss));
SHGetSetSettings(lpss, SSF_SORTCOLUMNS, False);
Upvotes: 2
Reputation: 5668
Here is TShellState definition in Delphi 2010:
type
tagSHELLSTATEW = record
Data: DWORD;
Data2: UINT;
{ fShowAllObjects: BOOL:1;
fShowExtensions: BOOL:1;
fNoConfirmRecycle: BOOL:1;
fShowSysFiles: BOOL:1;
fShowCompColor: BOOL:1;
fDoubleClickInWebView: BOOL:1;
fDesktopHTML: BOOL:1;
fWin95Classic: BOOL:1;
fDontPrettyPath: BOOL:1;
fShowAttribCol: BOOL:1;
fMapNetDrvBtn: BOOL:1;
fShowInfoTip: BOOL:1;
fHideIcons: BOOL:1;
fWebView: BOOL:1;
fFilter: BOOL:1;
fShowSuperHidden: BOOL:1;
fNoNetCrawling: BOOL:1;}
//dwWin95Unused: DWORD;// Win95 only - no longer supported pszHiddenFileExts
//uWin95Unused: UINT; // Win95 only - no longer supported cbHiddenFileExts
// Note: Not a typo! This is a persisted structure so we cannot use LPARAM
lParamSort: Integer;
iSortDirection: Integer;
version: UINT;
// new for win2k. need notUsed var to calc the right size of ie4 struct
// FIELD_OFFSET does not work on bit fields
uNotUsed: UINT;// feel free to rename and use
{ fSepProcess: BOOL:1;
// new for Whistler.
fStartPanelOn: BOOL:1;
fShowStartPage: BOOL:1;
// new for Windows Vista
fAutoCheckSelect: BOOL:1;
fIconsOnly: BOOL:1;
fShowTypeOverlay: BOOL:1;
// If you need a new flag, steal a bit from from fSpareFlags.
// Also, keep SHELLFLAGSTATE and SHGetSettings in sync when adding new flags.
fSpareFlags: UINT:11;
}
end;
{$EXTERNALSYM tagSHELLSTATEW}
SHELLSTATEA = tagSHELLSTATEW;
{$EXTERNALSYM SHELLSTATEA}
SHELLSTATEW = tagSHELLSTATEW;
{$EXTERNALSYM SHELLSTATEW}
SHELLSTATE = SHELLSTATEW;
{$EXTERNALSYM SHELLSTATE}
TShellState = SHELLSTATE;
PShellState = ^TShellState;
const
SHELLSTATEVERSION_IE4 = 9;
{$EXTERNALSYM SHELLSTATEVERSION_IE4}
SHELLSTATEVERSION_WIN2K = 10;
{$EXTERNALSYM SHELLSTATEVERSION_WIN2K}
Not very helpful, unfortunately.
Upvotes: 1
Reputation: 26376
Afaik bitfields in C are a subtype of integer. There are ways to pack it, but also in C, after a bunch of single bit fields, there will be padding to the next byte boundery (and probably even to the next integer boundery). Moreover C's sizeof doesn't support halves either.
So probably it is 1+6+1 times sizeof(integer)= 32bytes.
Upvotes: 0
Reputation: 6894
My reading of the help here is that the SSF_ constants are specified for the mask when retrieving data. There's no reason they have to map to the bits in the ShellState structure.
If they did fShowSysFiles would map to 8 (0x04), and we know from the help that SSF_SHOWSYSFILES is 0x20. There's no direct mapping.
Upvotes: 3