Вызов SHGetSetSettings из Delphi - PullRequest
3 голосов
/ 14 августа 2010

Я только что прочитал этот вопрос и этот вопрос , и с тех пор я пытаюсь вызвать SHGetSetSettings в Delphi.Это функция shell32.dll, но она не определена в ShlObj.pas, поэтому нам нужно написать собственное определение.

Сначала нам нужно перевести структуру SHELLSTATE.Сейчас у меня ограниченный опыт работы с Си, но я предполагаю, что «: 1» означает, что элемент структуры является одним битом, то есть восемь из них могут быть упакованы вместе в байт.Я также предполагаю, что DWORD = UINT = 32-разрядные целые числа без знака и что LONG = int являются 32-разрядными целыми числами со знаком.Но тогда возникает проблема: вся структура будет тогда занимать 228 бит, или 28,5 байта, что ... довольно невозможно, по крайней мере, в Delphi, где sizeof(SomeRecord) должно быть целым числом.

Тем не менееЯ попытался решить это, добавив четыре фиктивных бита в конце.232 бита = 29 байт, что приятно.

Поэтому я попытался

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;

, а затем объявил (для удобства позже)

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;

Теперь я чувствовал себя готовопределить

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

implementation
  procedure SHGetSetSettings; external shell32 name 'SHGetSetSettings';

Но прежде чем я попробовал код, я заметил кое-что очень странное.Я обнаружил, что объявленные мной константы уже были объявлены здесь: Константы SSF .Обратите внимание, что SSF_HIDEICONS = 0x00004000 = 16384 ≠ fHideIcons = 4096.Если константы SSF_ действительно являются масками, используемыми вместе с SHELLSTATE, то нет смысла определять SSF_HIDEICONS как 2 ^ 14, когда это 13-й бит (и его маска должна быть 2 ^ 12) в структуре.Следовательно, кажется, что две справочные страницы MSDN противоречат друг другу.

Может ли кто-нибудь внести некоторую ясность во все это?

Ответы [ 5 ]

3 голосов
/ 15 августа 2010

Мое чтение справки здесь заключается в том, что константы SSF_ указываются для маски при извлечении данных.Нет причин, по которым они должны отображаться в биты в структуре ShellState.

Если бы они это сделали, fShowSysFiles отобразил бы 8 (0x04), и мы знаем из справки, что SSF_SHOWSYSFILES - 0x20.Прямого сопоставления нет.

2 голосов
/ 15 августа 2010

Объявление D2010 для SHELLSTATE в ShlObj.pas, к сожалению, неверно, но первая группа битов (17) корректно совпадает с Data: DWORD; (у вас действительно все в порядке).Их может быть 18 или 19 одинаковых.Тогда мы должны получить еще 2 DWORD / UINT для 2 Win95unused, а не только Data2.

Жаль, потому что флаги SSF и объявления SHGetSetSettings уже сделаны и корректны.

Правильная декларация в соответствии с MSDN должна быть 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;

Вы можете убедиться, что это позволяет правильно получить свойства сортировки с помощью:

var
  lpss: tagSHELLSTATEW;
begin
  ZeroMemory(@lpss, SizeOf(lpss));
  SHGetSetSettings(lpss, SSF_SORTCOLUMNS, False);
1 голос
/ 15 августа 2010

Вот определение TShellState в 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}

К сожалению, не очень полезно.

0 голосов
/ 05 октября 2011

Я немного опоздал на вечеринку, но эта статья довольно хорошо объясняет битовые поля и предлагает несколько подходов для Delphi.

0 голосов
/ 15 августа 2010

Битовые поля Afaik в C являются подтипом целого числа.Есть способы упаковать его, но также в C, после нескольких однобитовых полей, будет заполнение до следующей байтовой границы (и, возможно, даже до следующей целочисленной границы).Более того, sizeof C также не поддерживает половины.

Так что, вероятно, он в 1 + 6 + 1 раз больше sizeof (integer) = 32 байта.

...