Что нового

[Ошибки] Смена обоев на рабочем столе

SyDr

Сидра
Сообщения
651
Репутация
158
Есть функция для смены обоев на рабочем столе (взято с офф. форума):
Код:
#Include <WinAPI.au3>
#include <GDIPlus.au3>

Global Const $SPI_SETDESKWALLPAPER            = 0x0014
Global Const $SPIF_UPDATEINIFILE                = 0x0001
Global Const $SPIF_SENDCHANGE                  = 0x0002

Func _ChangeDesktopBackground($sFile, $iPosition=3)
    Local $sCLSID, $tBuffer, $hImage, $sTemp

; Convert JPG image to BMP image
    _GDIPlus_Startup()
    $hImage = _GDIPlus_ImageLoadFromFile($sFile)
    $sCLSID = _GDIPlus_EncodersGetCLSID("BMP")
    $sTemp  = _Str_ChangeFileExt($sFile, ".bmp")
    _GDIPlus_ImageSaveToFile($hImage, $sTemp)
    _GDIPlus_ImageDispose($hImage)
    _GDIPlus_Shutdown()

; Set wallpaper position
    Switch $iPosition
        Case 1; Tile
            RegWrite('HKCU\Control Panel\Desktop', 'TileWallpaper' , 'reg_sz', '1')
            RegWrite('HKCU\Control Panel\Desktop', 'WallpaperStyle', 'reg_sz', '0')
        Case 2; Center
            RegWrite('HKCU\Control Panel\Desktop', 'TileWallpaper' , 'reg_sz', '0')
            RegWrite('HKCU\Control Panel\Desktop', 'WallpaperStyle', 'reg_sz', '0')
        Case 3; Stretch
            RegWrite('HKCU\Control Panel\Desktop', 'TileWallpaper' , 'reg_sz', '0')
            RegWrite('HKCU\Control Panel\Desktop', 'WallpaperStyle', 'reg_sz', '2')
    EndSwitch

; Set wallpaper
    $tBuffer = DllStructCreate("char Text[" & StringLen($sTemp) + 1 & "]")
    DllStructSetData($tBuffer, "Text", $sTemp)
    _WinAPI_SystemParametersInfo($SPI_SETDESKWALLPAPER, 1, DllStructGetPtr($tBuffer), BitOR($SPIF_UPDATEINIFILE, $SPIF_SENDCHANGE))
EndFunc

Func _Str_ChangeFileExt($sFileName, $sExtension)
  Local $iIndex

  $iIndex = _Str_LastDelimiter(".\:", $sFileName)
  if ($iIndex = 0) or (StringMid($sFileName, $iIndex, 1) <> ".") then $iIndex = StringLen($sFileName) + 1
  Return StringLeft($sFileName, $iIndex - 1) & $sExtension
EndFunc

Func _Str_LastDelimiter($sDelimiters, $sString)
  Local $iI, $iN, $sDelimiter

  for $iI = 1 to StringLen($sDelimiters)
    $sDelimiter = StringMid($sDelimiters, $iI, 1)
    $iN = StringInStr($sString, $sDelimiter, 0, -1)
    if $iN > 0 then Return $iN
  next
EndFunc


Однако у меня она почему-то не работает. Выдаёт ошибку:
2 The system cannot find the file specified. ERROR_FILE_NOT_FOUND
Сам файл по указанному пути существует. Система - Win7. Не работает только у меня?
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
SyDr [?]
Система выдаёт ошибку как я понял?
Возможно это проверка на наличие файла обоев указанного в реестре, и когда функция меняет это, система просто сообщает о не найденом файле. В любом случае это не ошибка AutoIt'а, т.ч ты видимо ошибься разделом :smile:

P.S
Я бы построчно убирал по одной функции (начиная с конца) и проверял, когда ошибка перестанет появляться тогда будет известно что конкретно это вызывает.
 

snoitaleR

AutoIT Гуру
Сообщения
855
Репутация
223
SyDr
У меня нет WIN7...
Проверь, пожалуйста, мой скрипт, который нормально работает в WINXP...

Код:
; НАЧАЛО

; Смена рисунка рабочего стола

 #include <gdiplus.au3>

 $SOURCE="X:\123.jpg"
 $TARGET=$SOURCE&".bmp"
 _GDIPlus_Startup()
 $IMAGE=_GDIPlus_ImageLoadFromFile($SOURCE)
 _GDIPlus_ImageSaveToFile($IMAGE,$TARGET)
 _GDIPlus_ShutDown()

 RegWrite('HKCU\Control Panel\Desktop','TileWallpaper' ,'reg_sz','0')
 RegWrite('HKCU\Control Panel\Desktop','WallpaperStyle','reg_sz','2')

 $tBuffer=DllStructCreate("char Text["&StringLen($TARGET)+1&"]")
 DllStructSetData($tBuffer,"Text",$TARGET)
 DllCall("user32.dll","int","SystemParametersInfo","int",0x0014,"int",0,"int",DllStructGetPtr($tBuffer),"int",0x0003)

; КОНЕЦ
 
Автор
SyDr

SyDr

Сидра
Сообщения
651
Репутация
158
CreatoR [?]
Система выдаёт ошибку как я понял?
Код:
$nError = _WinApiGetLastError() ; 2


snoitaleR, спасибо, работает.

Различия в приведённой функции и в функции WinApi:
WinApi:
DllCall("user32.dll", "bool", "SystemParametersInfoW", "uint", $iAction, "uint", $iParam, "ptr", $vParam, "uint", $iWinIni)
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
SyDr [?]
Ни одна из приведённых функции в примере не использует это, по крайней мере оно так в последней версии (3.3.6.1), что уже говорит о том что это (уже?) не баг.
 
Автор
SyDr

SyDr

Сидра
Сообщения
651
Репутация
158
CreatoR [?]
Ни одна из приведённых функции в примере не использует это, по крайней мере оно так в последней версии (3.3.6.1), что уже говорит о том что это (уже?) не баг.
Не понял >_<

Кстати, замечание к функции:
Remarks
This function always call the Unicode version so $vParam must be inaccordance when using strings.
............
А всё. Уже и разобрался. Формировать структуру надо просто как Юникод-строку и всё.
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
SyDr [?]
Что именно?

Ты привёл в пример имя функции («_WinApiGetLastError»), а я не нашёл её использование в функциях твоего примера (в первом сообщении, отсюда вывод - у тебя не последняя версия AutoIt'а.

Ну или ты просто её привёл чтобы показать как получал сообщение об ошибке, тогда нужно было упоминать об этом в начале...

Так всё таки, ты для себя может и решил проблему, а в оригинальной функции есть бага, или нет? если есть, как исправить? нужно тогда тикет отправить...
 
Автор
SyDr

SyDr

Сидра
Сообщения
651
Репутация
158
CreatoR [?]
Общий смысл предложения. Но теперь понял :smile:

Ты привёл в пример имя функции («_WinApiGetLastError»), а я не нашёл её использование в функциях твоего примера (в первом сообщении, отсюда вывод - у тебя не последняя версия AutoIt'а.
_WinApi_GetLastError. Я ошибся чуток. Многие функции из библиотеки возвращают только два значения (True или False). Если возвращённое значение False - _WinApi_GetLastError используется для определения кода возникшеё ошибки.

Так всё таки, ты для себя может и решил проблему, а в оригинальной функции есть бага, или нет? если есть, как исправить? нужно тогда тикет отправить...
Ошибки нет. Просто теперь при формировании параметров для функции нужно использовать не ANSI-строку, а Юникод-строку. Тогда, в примере из первого поста следует сменить строку
$tBuffer = DllStructCreate("char Text[" & StringLen($sTemp) + 1 & "]")
на
$tBuffer = DllStructCreate("wchar Text[" & StringLen($sTemp) + 1 & "]")
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
SyDr [?]
в примере из первого поста следует сменить строку
Нужно кажется ещё удвоить длину строки, т.к в юникодной версии длина одного символа равна 2-ум байтам.

Код:
$tBuffer = DllStructCreate("wchar Text[" & (StringLen($sTemp) * 2) + 1 & "]")
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Если используется Unicode версия API функции (символ "W" в конце), то все параметры для этой функции так же должны быть в Unicode представлении. Т.е. нужно использовать не "char", а "wchar". В последних версиях AutoIt и WinAPIEx UDF поддерживается только Unicode, следовательно всегда используем "wchar".

CreatoR сказал(а):
Нужно кажется ещё удвоить длину строки, т.к в юникодной версии длина одного символа равна 2-ум байтам.

Нет, не нужно, т.к. "wchar" и есть Unicode "wide char", длина которго равна 2-ум байтам.



Добавлено:
Сообщение автоматически объединено:

Проще записать так:

Код:
DllCall("user32.dll", "bool", "SystemParametersInfo", "uint", 0x0014, "uint", 0, "wstr", $TARGET, "uint", 0x0003)
 
Верх