Dokumentacja

Obsługa kompozycji Classic Window w Windows 8.1

Rozdział ten przeznaczony jest dla programistów, którzy chcą, aby dało się uruchomić ich programy z kompozycją klasyczną. W tym celu należy program napisać tak, aby obsługa GUI była jednakowa dla Windows 7 lub wcześniejszych oraz Windows 8.1. Nie są wymagane żadne specjalne środki.

Poniżej zawarte są wskazówki:

 * Nie używaj IsWindows8OrLater() oraz GetVersionEx() w celu sprawdzenia czy kompozycja jest osiągalna. Zastosuj poniższe funkcje do sprawdzenia czy kompozycje są aktywne i jaka kompozycja lub temat jest aktualnie załadowany.

 * DwmIsCompositionEnabled() zwraca wartość false.

 * IsCompositionActive() zwraca wartość false.

 * IsThemeActive() zwraca wartość false.

 * IsAppThemed() zwraca wartość false.

 * OpenThemeData() zwraca 0 oraz kod błędu 0x80070490.

 * GetCurrentThemeName() zwraca wartość 0x80070490.


Zdarzenie WM_COPYDATA wysyłane do Shell_TrayWnd (shell-coding)


Struktura przekazywana w parametrze lparam zdarzenia WM_COPYDATA ma następującą składnię:

typedef struct tagCOPYDATASTRUCT {
   ULONG_PTR dwData;
   DWORD     cbData;
   PVOID     lpData;
} COPYDATASTRUCT, *PCOPYDATASTRUCT;

Dla dwData równego:

 * 0: zdarzenie dotyczy wywołania funkcji SHAppBarMessage
lpData wskazuje na strukturę jedną ze struktur SHELLAPPBARDATA

 * 1: zdarzenie dotyczy funkcji Shell_NotifyIcon
lpData to wskaźnik na strukturę TRAYNOTIFYDATA

 * 2: zdarzenie dotyczy funkcji SHEnableServiceObject lub SHLoadInProc (niewspierane przez LeoShell ze względów bezpieczeństwa).


SHELLAPPBARDATA (dwData=0)

Struktura ta może występować w jednej z trzech wersji zależnie od systemu operacyjnego (dokładniej: wersji biblioteki shell32.dll):

Gdy cbData=64, struktura SHELLAPPBARDATA ma postać:
typedef struct{
   APPBARDATA appBarData;
   DWORD lparamExtensionTo64bit; // The cbSize of APPBARDATA is incremented by 4
   DWORD message;
   DWORD unused1; // random (often 0), probably a leak from a calling process
   DWORD dataAtom;
   DWORD unknown1; // always zero during my tests
   DWORD destinationProcessId;
   DWORD unused2;  // random (often 0), probably a leak from the calling process
} SHELLAPPBARDATAV3;

/* The atom contains (in its name) encoded data.
   The coding is similar but not identical to base64.
   There is an encoded ATOMDATA structure. */

typedef struct{
   char anIdentifier[4];       // This contains "MARC" [maybe reversed "CRAM"?] (-;
   DWORD unknown1;             // always zero during my tests.
   QWORD hFileMapObject;       // 64-bit handle
   DWORD destinationProcessId;
   DWORD unknown2;             // always zero during my tests.
} ATOMDATA, *PATOMDATA;

/* After correct decoding, the destinationProcessId from SHELLAPPBARDATAV3
   and destinationProcessId from ATOMDATA shall be identical and equal to GetCurrentProcessId().

   If you want to return any data to the calling process, you can call:
   char* temp=MapViewOfFile(hFileMapObject, FILE_MAP_WRITE, 0, 0, 56);
   APPBARDATA* rapd=(APPBARDATA*)(temp+16); // cbSize of "rapd" shall be set to 40.

   After returning the data, do not forget call:
   UnmapViewOfFile(temp);
*/

// This function converts atom to ATOMDATA structure.
bool atom2atomData(long atom, ATOMDATA &data)
{
   char name[34]={0};
   unsigned long decode[6]={
      0x20820820,
      0x08208208,
      0x82082082,
      0x20820820,
      0x08208208,
      0x82082082
   };
   int i, idx, sh;
   if(!atom) return false;
   GlobalGetAtomNameA(atom, name, 33);
   if(name[32] || !name[31]) return false;   // length smaller or greater than 32 bytes
   idx=0;
   sh=0;
   for(i=0; i<32; i++)
   {
      decode[idx]^=((unsigned char)name[i]&0x3F) << sh;
      if (idx<5 && sh) decode[idx+1]^=((unsigned char)name[i]&0x3F) >> (32-sh);
      sh+=6;
      if(sh>31)
      {
         sh&=0x1F;
         idx++;
      }
   }
   CopyMemory(&data, decode, 24);
   return true;
}

Pozycjonowanie okien

LeoShell posiada rozszerzoną obsługę stylów okien. Nieudokumentowany i nieużywany styl WS_EX_DRAGDETECT=0x02L został zastąpiony stylem WS_EX_STAYONBOTTOM=0x02L, który powoduje pozostawanie okien poniżej zwykłych okien – blisko pulpitu. Styl ma zastosowanie tylko dla głównych okien aplikacji. Jego użycie dla innych okien nie przynosi żadnego działania.

Przewidziane są 3 dodatkowe komendy systemowe dla zdarzenia WM_SYSCOMMAND:

 * SC_STAYONTOP=0xF800: powoduje przesunięcie okien aplikacji na pierwszy plan,

 * SC_STAYONBOTTOM=0xF810: powoduje przesunięcie okien aplikacji na ostatni plan,

 * SC_NORMALZPOSITION=0xF820: powoduje przywrócenie domyślnego planu dla okien aplikacji.

LPARAM dla tych komend pozostaje nieużywany i powinien być równy zero podczas wysyłania zdarzenia.