
Получение и изменение обоев рабочего стола на Ассемблере
Тема обоев рабочего стола Windows уже поднималась тут несколько раз, но это были, в основном, какие-то готовые программные решения. Настало время заглянуть "под капот" системы и посмотреть, как оно устроено. А лучшего инструмента, чем Ассемблер, для этих целей сложно придумать.Начнем с получения информации об установленных обоях рабочего стола. Тут ничего сложного, достаточно вызвать функцию SystemParametersInfo с параметром SPI_GETDESKWALLPAPER.
Code (Assembler) : Убрать нумерацию
- SPI_GETDESKWALLPAPER = 0x0073
- invoke SystemParametersInfo,SPI_GETDESKWALLPAPER,\
- MAX_PATH,szPath,0
- ; szPath -> строка пути к файлу обоев
Теперь переходим к смене обоев рабочего стола. В интернетах для этих целей обычно рекомендуют использовать упомянутую выше функцию SystemParametersInfo с параметром SPI_SETDESKWALLPAPER. Код получается минимальный, все очень просто реализуется, выглядит на первый взгляд стильно, модно, молодежно.
Code (Assembler) : Убрать нумерацию
- ; Путь к файлу с новыми обоями рабочего стола
- szPath db 'c:\windows\wallpaper.bmp',0
- SPI_SETDESKWALLPAPER = 20
- SPIF_SENDWININICHANGE = 2
- SPIF_UPDATEINIFILE = 1
- invoke SystemParametersInfo,SPI_SETDESKWALLPAPER,\
- 0,szPath,SPIF_UPDATEINIFILE+SPIF_SENDWININICHANGE
Давайте сделаем все по-правильному, то есть с использованием технологии COM и системного интерфейса IActiveDesktop. FASM про все это колдунство вообще не в курсе, так что начинаем как обычно, то есть с описания структур, интерфейсов и GUID'ов.
Code (Assembler) : Убрать нумерацию
- ; GUID {75048700-EF1F-11D0-9888-006097DEACF9}
- CLSID_ActiveDesktop dd 075048700h
- dw 0EF1Fh
- dw 011D0h
- db 098h, 088h, 000h, 060h, 097h, 0DEh, 0ACh, 0F9h
- ; GUID {F490EB00-1240-11D1-9888-006097DEACF9}
- IID_IActiveDesktop dd 0F490EB00h
- dw 01240h
- dw 011D1h
- db 098h, 088h, 000h, 060h, 097h, 0DEh, 0ACh, 0F9h
- ; IID_IActiveDesktop Interface
- struct IActiveDesktop
- ; IUnknown
- QueryInterface dd ? ; 000h
- AddRef dd ? ; 004h
- Release dd ? ; 008h
- ; IActiveDesktop
- ApplyChanges dd ? ; 00Ch
- GetWallpaper dd ? ; 010h
- SetWallpaper dd ? ; 014h
- GetWallpaperOptions dd ? ; 018h
- SetWallpaperOptions dd ? ; 01Ch
- GetPattern dd ? ; 020h
- SetPattern dd ? ; 024h
- GetDesktopItemOptions dd ? ; 028h
- SetDesktopItemOptions dd ? ; 02Ch
- AddDesktopItem dd ? ; 030h
- AddDesktopItemWithUI dd ? ; 034h
- ModifyDesktopItem dd ? ; 038h
- RemoveDesktopItem dd ? ; 03Ch
- GetDesktopItemCount dd ? ; 040h
- GetDesktopItem dd ? ; 044h
- GetDesktopItemByID dd ? ; 048h
- GenerateDesktopItemHtml dd ? ; 04Ch
- AddUrl dd ? ; 050h
- GetDesktopItemBySource dd ? ; 054h
- ends
- ; Настройки отображения обоев
- struct WALLPAPEROPT
- dwSize dd ?
- dwStyle dd ?
- ends
- CLSCTX_INPROC_SERVER = 1
- S_OK = 0
- WPSTYLE_CENTER = 0
- WPSTYLE_TILE = 1
- WPSTYLE_STRETCH = 2
- WPSTYLE_KEEPASPECT = 3
- WPSTYLE_CROPTOFIT = 4
- WPSTYLE_SPAN = 5
- AD_APPLY_SAVE = 1
- AD_APPLY_HTMLGEN = 2
- AD_APPLY_REFRESH = 4
- AD_APPLY_FORCE = 8
- AD_APPLY_BUFFERED_REFRESH = 0x00000010
- AD_APPLY_DYNAMICREFRESH = 0x00000020
- AD_APPLY_ALL = AD_APPLY_SAVE+AD_APPLY_HTMLGEN+AD_APPLY_REFRESH
Code (Assembler) : Убрать нумерацию
- invoke CoInitialize,0
- ; Создать объект
- invoke CoCreateInstance,CLSID_ActiveDesktop,NULL,\
- CLSCTX_INPROC_SERVER,\
- IID_IActiveDesktop,pIActDesk
- cmp eax,S_OK
- jne loc_exit
- ; Получить путь к файлу обоев
- mov eax, [pIActDesk]
- mov eax, [eax]
- stdcall dword [eax+IActiveDesktop.GetWallpaper],\
- [pIActDesk],szPath,MAX_PATH,0
- ; Получить параметры отображения
- mov [wpOpt.dwSize],sizeof.WALLPAPEROPT
- mov eax, [pIActDesk]
- mov eax, [eax]
- stdcall dword [eax+IActiveDesktop.GetWallpaperOptions],\
- [pIActDesk],wpOpt,0
- ; Прибраться за собой
- mov eax, [pIActDesk]
- mov eax, [eax]
- stdcall dword [eax+IActiveDesktop.Release],[pIActDesk]
- ; szPath -> строка пути к файлу обоев
- ; wpOpt.dwStyle -> стиль отображения обоев
- loc_exit:
- ; Удалить объект
- invoke CoUninitialize
Code (Assembler) : Убрать нумерацию
- invoke CoInitialize,0
- ; Создать объект
- invoke CoCreateInstance,CLSID_ActiveDesktop,NULL,\
- CLSCTX_INPROC_SERVER,\
- IID_IActiveDesktop,pIActDesk
- cmp eax,S_OK
- jne loc_exit
- ; Установить новые обои рабочего стола
- mov eax, [pIActDesk]
- mov eax, [eax]
- stdcall dword [eax+IActiveDesktop.SetWallpaper],\
- [pIActDesk],szPath,0
- ; Установить параметры отображения
- mov [wpOpt.dwSize],sizeof.WALLPAPEROPT
- mov [wpOpt.dwStyle],WPSTYLE_CENTER
- mov eax, [pIActDesk]
- mov eax, [eax]
- stdcall dword [eax+IActiveDesktop.SetWallpaperOptions],\
- [pIActDesk],wpOpt,0
- ; Применить изменения
- mov eax, [pIActDesk]
- mov eax, [eax]
- stdcall dword [eax+IActiveDesktop.ApplyChanges],[pIActDesk],\
- AD_APPLY_ALL
- ; Прибраться за собой
- mov eax, [pIActDesk]
- mov eax, [eax]
- stdcall dword [eax+IActiveDesktop.Release],[pIActDesk]
- loc_exit:
- ; Удалить объект
- invoke CoUninitialize
Code (Assembler) : Убрать нумерацию
- ; GUID {C2CF3110-460E-4FC1-B9D0-8A1C0C9CC4BD}
- CLSID_DesktopWallpaper \
- dd 0C2CF3110h
- dw 0460Eh
- dw 04FC1h
- db 0B9h, 0D0h, 08Ah, 01Ch, 00Ch, 09Ch, 0C4h, 0BDh
- ; GUID {B92B56A9-8B55-4E14-9A89-0199BBB6F93B}
- IID_IDesktopWallpaper \
- dd 0B92B56A9h
- dw 08B55h
- dw 04E14h
- db 09Ah, 089h, 001h, 099h, 0BBh, 0B6h, 0F9h, 03Bh
- ; IID_IDesktopWallpaper Interface
- struct IDesktopWallpaper
- ; IUnknown
- QueryInterface dd ? ; 000h
- AddRef dd ? ; 004h
- Release dd ? ; 008h
- ; IDesktopWallpaper
- SetWallpaper dd ? ; 00Ch
- GetWallpaper dd ? ; 010h
- GetMonitorDevicePathAt dd ? ; 014h
- GetMonitorDevicePathCount dd ? ; 018h
- GetMonitorRECT dd ? ; 01Ch
- SetBackgroundColor dd ? ; 020h
- GetBackgroundColor dd ? ; 024h
- SetPosition dd ? ; 028h
- GetPosition dd ? ; 02Ch
- SetSlideshow dd ? ; 030h
- GetSlideshow dd ? ; 034h
- SetSlideshowOptions dd ? ; 038h
- GetSlideshowOptions dd ? ; 03Ch
- AdvanceSlideshow dd ? ; 040h
- GetStatus dd ? ; 044h
- Enable dd ? ; 048h
- ends
- CLSCTX_INPROC_SERVER = 0x01
- CLSCTX_LOCAL_SERVER = 0x04
- CLSCTX_REMOTE_SERVER = 0x10
- CLSCTX_SERVER = CLSCTX_INPROC_SERVER + CLSCTX_LOCAL_SERVER\
- + CLSCTX_REMOTE_SERVER
Code (Assembler) : Убрать нумерацию
- invoke CoInitialize,0
- ; Создать объект
- invoke CoCreateInstance,CLSID_DesktopWallpaper,NULL,\
- CLSCTX_SERVER,\
- IID_IDesktopWallpaper,pIDskWp
- cmp eax,S_OK
- jne loc_exit
- ; Получить количество мониторов
- mov eax, [pIDskWp]
- mov eax, [eax]
- stdcall dword [eax+IDesktopWallpaper.GetMonitorDevicePathCount],\
- [pIDskWp],dMonCount
- xor ebx,ebx
- loc_loop:
- ; Получить следующий монитор
- mov eax, [pIDskWp]
- mov eax, [eax]
- stdcall dword [eax+IDesktopWallpaper.GetMonitorDevicePathAt],[pIDskWp],\
- ebx,lpMon
- ; [lpMon] -> указатель на строку-идентификатор монитора
- ; Получить обои на этом мониторе
- mov eax, [pIDskWp]
- mov eax, [eax]
- stdcall dword [eax+IDesktopWallpaper.GetWallpaper],[pIDskWp],\
- [lpMon],lpWP
- ; [lpWP] -> указатель на строку с именем файла изображения
- ; Все мониторы обработали?
- inc ebx
- cmp ebx,[dMonCount]
- jb loc_loop
- ; Прибраться за собой
- mov eax, [pIDskWp]
- mov eax, [eax]
- stdcall dword [eax+IDesktopWallpaper.Release],[pIDskWp]
- loc_exit:
- ; Удалить объект
- invoke CoUninitialize
Code (Assembler) : Убрать нумерацию
- invoke CoInitialize,0
- ; Создать объект
- invoke CoCreateInstance,CLSID_DesktopWallpaper,NULL,\
- CLSCTX_SERVER,\
- IID_IDesktopWallpaper,pIDskWp
- cmp eax,S_OK
- jne loc_exit
- ; Получить количество мониторов
- mov eax, [pIDskWp]
- mov eax, [eax]
- stdcall dword [eax+IDesktopWallpaper.GetMonitorDevicePathCount],\
- [pIDskWp],dMonCount
- xor ebx,ebx
- loc_loop:
- ; Получить следующий монитор
- mov eax, [pIDskWp]
- mov eax, [eax]
- stdcall dword [eax+IDesktopWallpaper.GetMonitorDevicePathAt],[pIDskWp],\
- ebx,lpMon
- ; Установить обои на этом мониторе
- mov eax, [pIDskWp]
- mov eax, [eax]
- stdcall dword [eax+IDesktopWallpaper.SetWallpaper],[pIDskWp],\
- [lpMon],szPath
- ; Все мониторы обработали?
- inc ebx
- cmp ebx,[dMonCount]
- jb loc_loop
- ; Установить стиль отображения для всех мониторов
- mov eax, [pIDskWp]
- mov eax, [eax]
- stdcall dword [eax+IDesktopWallpaper.SetPosition],[pIDskWp],\
- DWPOS_STRETCH
- ; Прибраться за собой
- mov eax, [pIDskWp]
- mov eax, [eax]
- stdcall dword [eax+IDesktopWallpaper.Release],[pIDskWp]
- loc_exit:
- ; Удалить объект
- invoke CoUninitialize
Просмотров: 729 | Комментариев: 3

Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье
ManHunter
(15.02.2025 в 23:07):
Дополнил статью примером работы с IDesktopWallpaper, архив обновлен.

ManHunter
(19.01.2023 в 14:58):
Да я никуда не тороплюсь. Работает и ладно.

Grey
(19.01.2023 в 14:53):
На 32 битах до пенсии не просидишь). Консерватизм думаю связан с неудобством восприятия таких длинных чисел. Да и разработчики компиляторов и дебагеров, если не на 64 то 128 битах задумаются о замене hex-представления на более высокие порядки.

Добавить комментарий
Заполните форму для добавления комментария
