quoi - qu'est ce qu'un tag en informatique



Appel de SHGetSetSettings à partir de Delphi (4)

La déclaration D2010 de SHELLSTATE dans ShlObj.pas est malheureusement incorrecte, mais le premier groupe de bits (17) est correctement mis en correspondance avec Data: DWORD; (Le tien est en effet OK). Il pourrait y en avoir 18 ou 19 tout de même. Ensuite, nous devrions obtenir 2 DWORD / UINT supplémentaires pour les 2 Win95unused, et pas seulement Data2.

Dommage car les drapeaux SSF et les déclarations SHGetSetSettings sont déjà faites dedans et correctes.

La déclaration correcte selon MSDN doit être 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;

Vous pouvez vérifier que cela permet d'obtenir correctement les propriétés de tri avec:

var
  lpss: tagSHELLSTATEW;
begin
  ZeroMemory(@lpss, SizeOf(lpss));
  SHGetSetSettings(lpss, SSF_SORTCOLUMNS, False);

https://ffff65535.com

Je viens de lire cette question et cette question , et depuis, j'ai essayé d'appeler SHGetSetSettings dans Delphi. C'est une fonction de shell32.dll , mais elle n'est pas définie dans ShlObj.pas , nous devons donc écrire notre propre définition.

Nous devons d'abord traduire la structure SHELLSTATE . Maintenant, je n'ai qu'une expérience limitée en C, mais je suppose que ": 1" signifie que le membre de la structure est un seul bit, c'est-à-dire que huit d'entre eux peuvent être emballés ensemble dans un octet. Je suppose également que DWORD = UINT = entiers non signés de 32 bits et que LONG = int sont des entiers signés de 32 bits. Mais alors nous avons un problème: la structure entière occupera alors 228 bits, soit 28,5 octets, ce qui est plutôt impossible, du moins en Delphi, où sizeof(SomeRecord) doit être un entier.

Néanmoins, j'ai essayé de le résoudre en ajoutant quatre bits factices à la fin. 232 bits = 29 octets, ce qui est bien.

D'où j'ai essayé

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;

et puis j'ai déclaré (pour plus de commodité)

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;

Maintenant je me sentais prêt à définir

interface
  procedure SHGetSetSettings(var ShellState: TShellState; Mask: cardinal; DoSet: boolean); stdcall;

implementation
  procedure SHGetSetSettings; external shell32 name 'SHGetSetSettings';

Mais avant d'essayer le code, j'ai remarqué quelque chose de très étrange. J'ai trouvé que les constantes que j'ai déclarées étaient déjà déclarées ici: Constantes SSF . Notez que SSF_HIDEICONS = 0x00004000 = 16384 ≠ fHideIcons = 4096 . Si les constantes SSF_ sont réellement des masques utilisés avec SHELLSTATE , cela n'a aucun sens de définir SSF_HIDEICONS comme 2 ^ 14 lorsqu'il s'agit du 13ème bit (et son masque devrait être 2 ^ 12) dans la structure. Il semble donc que les deux pages de référence MSDN se contredisent.

Quelqu'un pourrait-il clarifier tout cela?


Les champs de bits Afaik dans C sont un sous-type d'entier. Il y a des façons de l'empaqueter, mais aussi en C, après un tas de champs à un seul bit, il y aura un remplissage à la prochaine octet (et probablement même à la suivante). De plus, sizeof de C ne supporte pas non plus les moitiés.

Donc probablement c'est 1 + 6 + 1 fois sizeof (entier) = 32bytes.


Voici la définition de TShellState dans 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}

Pas très utile, malheureusement.


Je suis un peu en retard à la fête, mais cet article explique très bien bitfields et a quelques approches pour Delphi.





msdn