Что нового

_GDIPlus_DIBitmapCreateFromBitmap не загружает картинки в скомп. скрипте

Pat4005

Новичок
Сообщения
85
Репутация
4
Здравствуйте. Проблема такая же, что и у товарища в этом посте. А именно после совместного использования _LoadResourceImage() для загрузки ресурсов и _GDIPlus_DIBitmapCreateFromBitmap() для установки полупрозрачных изображений на элементы управления на их месте появляются чёрные области. Такое происходит только при непосредственном использовании _LoadResourceImage(), то есть только в скомпилированном скрипте. Фото "ДО" и "ПОСЛЕ" прилагаются. Если необходим код для анализа, то могу наклепать пример, но, повторюсь, проблема идентична указанной в посте по ссылке выше.

P. S. Я наконец-то добрался до истины, долго искал как создавать элементы без фона, с прозрачностью и полупрозрачностью, как всё это упаковывать и извлекать в виде ресурсов (безгранично благодарен Yashied'у) и многое другое. И вот я в шаге от "идеального GUI" :smile: и тут такое.. :'( Всех благодарю заранее за любую помощь!
 

Вложения

  • ДО.png
    ДО.png
    25.6 КБ · Просмотры: 4
  • ПОСЛЕ.png
    ПОСЛЕ.png
    3.4 КБ · Просмотры: 3

firex

AutoIT Гуру
Сообщения
943
Репутация
208
Pat4005
Код:
_GDIPlus_BitmapCreateFromHBITMAP

Натравите ее на результат функции _LoadResourceImage()
 
Автор
P

Pat4005

Новичок
Сообщения
85
Репутация
4
firex, сначала так и было, но из-за отсутствия поддержки этой функцией полупрозрачности вокруг изображений появлялся неприятный на вид контур.
 

firex

AutoIT Гуру
Сообщения
943
Репутация
208
Pat4005
Я все равно сглупил в предыдущем посте. Функция _GDIPlus_DIBitmapCreateFromBitmap принимает BITMAP, а не HBITMAP.

Предоставьте ваш код и я на досуге поищу проблему, есть предположения что у вас там не верно, но вслепую тыкать не буду.
 
Автор
P

Pat4005

Новичок
Сообщения
85
Репутация
4
firex, вот код:
Код:
#AutoIt3Wrapper_Res_File_Add=button1.png, PNG, button1
#AutoIt3Wrapper_Res_File_Add=button2.png, PNG, button2
#AutoIt3Wrapper_Res_File_Add=button3.png, PNG, button3

#Include <GDIPlus.au3>
#Include <WinAPIEx.au3>
#include <GUICtrlOnHover.au3>

$hForm = GUICreate('Transparent images on Pic control', 440, 222)
GUISetBkColor(0xFFFFFF)
$hPic1 = GUICtrlCreatePic('', 4, 4, 214, 214)
_ImageAssign(-1, 'PNG', 'button1') ; Изображение с поддержкой полупрозрачности (Device Independent Image))
_GUICtrl_OnHoverRegister(-1, '_ButtonHover', '_ButtonNormal', '_ButtonDown', '_ButtonUp')
$hButton1 = GUICtrlCreateDummy()
$hPic2 = GUICtrlCreatePic('', 222, 4, 214, 214)
_ImageAssign(-1, 'PNG', 'button1', 1) ; Изображение без поддержки полупрозрачности (Device Dependent Image))
_GUICtrl_OnHoverRegister(-1, '_ButtonHover', '_ButtonNormal', '_ButtonDown', '_ButtonUp')
$hButton2 = GUICtrlCreateDummy()

GUISetState()

While GUIGetMsg() <> -3
	$nMsg = GUIGetMsg()
	Switch $nMsg
		Case $hButton1
			MsgBox(0, '', 'Pressed first button')
		Case $hButton2
			MsgBox(0, '', 'Pressed second button')
	EndSwitch
WEnd


; Действия с кнопкой по умолчанию
Func _ButtonNormal($idCtrl)
	Switch $idCtrl
		Case $hPic1
			_ImageAssign($hPic1, 'PNG', 'button1')
		Case $hPic2
			_ImageAssign($hPic2, 'PNG', 'button1', 1)
	EndSwitch
EndFunc

; Действия с кнопкой при наведении
Func _ButtonHover($idCtrl)
	Switch $idCtrl
		Case $hPic1
			_ImageAssign($hPic1, 'PNG', 'button2')
		Case $hPic2
			_ImageAssign($hPic2, 'PNG', 'button2', 1)
	EndSwitch
EndFunc

; Действия с кнопкой при нажатии
Func _ButtonDown($idCtrl)
	Switch $idCtrl
		Case $hPic1
			_ImageAssign($hPic1, 'PNG', 'button3')
		Case $hPic2
			_ImageAssign($hPic2, 'PNG', 'button3', 1)
	EndSwitch
EndFunc

; Действия с кнопкой при отжатии
Func _ButtonUp($idCtrl)
	Switch $idCtrl
		Case $hPic1
			_ImageAssign($hPic1, 'PNG', 'button2')
			GUICtrlSendToDummy($hButton1)
		Case $hPic2
			_ImageAssign($hPic2, 'PNG', 'button2', 1)
			GUICtrlSendToDummy($hButton2)
	EndSwitch
EndFunc

; Анимация кнопок
Func _ImageAssign($hCtl, $sResType, $sResName, $iSemiOpacity = 0, $iWidth = 0, $iHeight = 0)
	Local $hCtrl, $hImage, $hBitmap
	Local Const $STM_SETIMAGE = 0x0172
	Local Const $IMAGE_BITMAP = 0
	
	$hCtl = GUICtrlGetHandle($hCtl)
	If Not $hCtl Then Return SetError(1, 0, 0)

	_GDIPlus_Startup()
	$hImage = _GDIPlus_ImageLoadFromFile(@ScriptDir&'\'&$sResName&'.png')
	If @Compiled Then $hImage = _LoadResourceImage(@ScriptFullPath, $sResType, $sResName)
	If BitAND($iWidth, $iHeight) Then $hImage = _GDIPlus_GetImageThumbnail($hImage, $iWidth, $iHeight)
	If $iSemiOpacity Then
		$hBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage)
	Else
		$hBitmap = _GDIPlus_DIBitmapCreateFromBitmap($hImage)
	EndIf
	_SendMessage($hCtl, $STM_SETIMAGE, $IMAGE_BITMAP, $hBitmap)
	
	_GDIPlus_ImageDispose($hImage)
	_GDIPlus_Shutdown()
EndFunc ;==>_ImageAssign

; Масштабирование (изменение размера) изображений
Func _GDIPlus_GetImageThumbnail($hImage, $iWidth, $iHeight)
	Local $Ret = DllCall($__g_hGDIPDll, 'int', 'GdipGetImageThumbnail', 'ptr', $hImage, 'int', $iWidth, 'int', $iHeight, 'ptr*', 0, 'ptr', 0, 'ptr', 0)
	
	If (@error) Or ($Ret[0]) Then
		Return SetError(1, 0, 0)
	EndIf
	
	Return $Ret[4]
EndFunc ;==>_GDIPlus_GetImageThumbnail

; Создание DeviceIndependentBitmap, поддерживающего полупрозрачность
Func _GDIPlus_DIBitmapCreateFromBitmap($hBitmap)
	
	Local $tBIHDR, $tMap, $pBits, $hImage, $hResult, $Width, $Height
	
	$Width = _GDIPlus_ImageGetWidth($hBitmap)
	$Height = _GDIPlus_ImageGetHeight($hBitmap)
	If ($Width < 1) Or ($Height < 1) Then
		Return 0
	EndIf
	$hImage = _GDIPlus_BitmapCloneArea($hBitmap, 0, 0, $Width, $Height, $GDIP_PXF32ARGB)
	$tMap = _GDIPlus_BitmapLockBits($hImage, 0, 0, $Width, $Height, $GDIP_ILMREAD, $GDIP_PXF32ARGB)
	$tBIHDR = DllStructCreate($tagBITMAPINFOHEADER)
	DllStructSetData($tBIHDR, 'biSize', DllStructGetSize($tBIHDR))
	DllStructSetData($tBIHDR, 'biWidth', $Width)
	DllStructSetData($tBIHDR, 'biHeight', $Height)
	DllStructSetData($tBIHDR, 'biPlanes', 1)
	DllStructSetData($tBIHDR, 'biBitCount', 32)
	DllStructSetData($tBIHDR, 'biCompression', $BI_RGB)
	$hResult = _WinAPI_CreateDIBSection(0, $tBIHDR, $DIB_RGB_COLORS, $pBits)
	If Not @Error Then
		_WinAPI_SetBitmapBits($hResult, $Width * $Height * 4, DllStructGetData($tMap, 'Scan0'))
	EndIf
	_GDIPlus_BitmapUnlockBits($hImage, $tMap)
	_GDIPlus_BitmapDispose($hImage)
	Return $hResult
EndFunc ;==>_GDIPlus_DIBitmapCreateFromBitmap

; Загрузка изображений из ресурсов исполняемого файла
Func _LoadResourceImage($hInstance, $sResType, $sResName, $iResLanguage = 0)
	Local $hInfo, $hData, $pData, $iSize, $hMem, $pMem, $hStream, $hImage

	If $iResLanguage Then
		$hInfo = _WinAPI_FindResourceEx($hInstance, $sResType, $sResName, $iResLanguage)
	Else
		$hInfo = _WinAPI_FindResource($hInstance, $sResType, $sResName)
	EndIf
	$hData = _WinAPI_LoadResource($hInstance, $hInfo)
	$iSize = _WinAPI_SizeOfResource($hInstance, $hInfo)
	$pData = _WinAPI_LockResource($hData)
	If @error Then
		Return SetError(1, 0, 0)
	EndIf
	$hMem = DllCall("kernel32.dll", "ptr", "GlobalAlloc", "uint", 2, "ulong_ptr", $iSize)
	If @error Then
		Return SetError(1, 0, 0)
	EndIf
	$pMem = DllCall("kernel32.dll", "ptr", "GlobalLock", "ptr", $hMem[0])
	If @error Then
		Return SetError(1, 0, 0)
	EndIf
	DllCall("kernel32.dll", "none", "RtlMoveMemory", "ptr", $pMem[0], "ptr", $pData, "ulong_ptr", $iSize)
	DllCall("kernel32.dll", "int", "GlobalUnlock", "ptr", $hMem[0])
	$hStream = _WinAPI_CreateStreamOnHGlobal($hMem[0])
	If @error Then
		Return SetError(1, 0, 0)
	EndIf
	_GDIPlus_Startup()
	$hImage = DllCall("gdiplus.dll", "uint", "GdipCreateBitmapFromStream", "ptr", $hStream, "ptr*", 0)
	If (@error) Or ($hImage[0]) Or (Not $hImage[2]) Then
		$hImage = 0
	EndIf
	_GDIPlus_Shutdown()
	DllCall("kernel32.dll", "ptr", "GlobalFree", "ptr", $hMem[0])
	If Not IsArray($hImage) Then
		Return SetError(1, 0, 0)
	EndIf
	
	Return $hImage[2]
EndFunc   ;==>_LoadResourceImage


Пока писал пример, нашёл причину, по которой фон элементов становился чёрным. Дело в использовании GUICtrlOnHover UDF от Creator'а. Но без неё то, чего я пытаюсь добиться, становится бессмысленным, так что вопрос остаётся открытым.
 

Вложения

  • button1.png
    button1.png
    11.8 КБ · Просмотры: 2
  • button2.png
    button2.png
    14.1 КБ · Просмотры: 2
  • button3.jpg
    button3.jpg
    7 КБ · Просмотры: 1
Автор
P

Pat4005

Новичок
Сообщения
85
Репутация
4
последнюю картинку залил в jpg, перезаливаю в png
 

Вложения

  • button3.png
    button3.png
    181.8 КБ · Просмотры: 1
Автор
P

Pat4005

Новичок
Сообщения
85
Репутация
4
Я наконец нашёл то, что нужно! Есть ещё одна функция, которая называется несколько иначе, а именно _GDIPlus_BitmapCreateDIBFromBitmap(). Устроена она по другому, и я не знаю как это работает, но оно работает. PNG загружаются на форму в первозданном виде! :laugh:

Вот сама функция:
Код:
; Создание DeviceIndependentBitmap, поддерживающего полупрозрачность
Func _GDIPlus_BitmapCreateDIBFromBitmap($hBitmap)
	Local $tBIHDR, $Ret, $tData, $pBits, $hResult = 0

	$Ret = DllCall($__g_hGDIPDll, 'uint', 'GdipGetImageDimension', 'ptr', $hBitmap, 'float*', 0, 'float*', 0)
	If (@error) Or ($Ret[0]) Then Return 0
	$tData = _GDIPlus_BitmapLockBits($hBitmap, 0, 0, $Ret[2], $Ret[3], $GDIP_ILMREAD, $GDIP_PXF32ARGB)
	$pBits = DllStructGetData($tData, 'Scan0')
	If Not $pBits Then Return 0
	$tBIHDR = DllStructCreate('dword;long;long;ushort;ushort;dword;dword;long;long;dword;dword')
	DllStructSetData($tBIHDR, 1, DllStructGetSize($tBIHDR))
	DllStructSetData($tBIHDR, 2, $Ret[2])
	DllStructSetData($tBIHDR, 3, $Ret[3])
	DllStructSetData($tBIHDR, 4, 1)
	DllStructSetData($tBIHDR, 5, 32)
	DllStructSetData($tBIHDR, 6, 0)
	$hResult = DllCall('gdi32.dll', 'ptr', 'CreateDIBSection', 'hwnd', 0, 'ptr', DllStructGetPtr($tBIHDR), 'uint', 0, 'ptr*', 0, 'ptr', 0, 'dword', 0)
	If (Not @error) And ($hResult[0]) Then
		DllCall('gdi32.dll', 'dword', 'SetBitmapBits', 'ptr', $hResult[0], 'dword', $Ret[2] * $Ret[3] * 4, 'ptr', DllStructGetData($tData, 'Scan0'))
		$hResult = $hResult[0]
	Else
		$hResult = 0
	EndIf
	_GDIPlus_BitmapUnlockBits($hBitmap, $tData)
	
	Return $hResult
EndFunc ;==>_GDIPlus_BitmapCreateDIBFromBitmap


P. S.: Всем спасибо за помощь. :ok:
 
Верх