Что нового

прозрачное окно произвольной формы (неправильная отрисовка)

damien2008

Осваивающий
Сообщения
178
Репутация
34
всем привет. прошу помочь.
есть набросок по примерам..
пытаюсь создать окно произвольной формы из PNG рисунка, поверх него создаю дочернее с кнопкой.
проблемы: дочернее полностью перекрывает подложкой родительское окно.
code:
Код:
#AutoIt3Wrapper_Res_File_Add=green.png, rt_rcdata, green
#AutoIt3Wrapper_Res_File_Add=grey.png, rt_rcdata, grey

#NoTrayIcon
#include <GDIPlus.au3>
#include <GuiComboBox.au3>
#include <File.au3>
#include <Array.au3>
#include <WindowsConstants.au3>
#include <GuiConstantsEx.au3>
#include <ButtonConstants.au3>
#Include <Memory.au3>
#Include <WinAPIEx.au3>
#include <Constants.au3>
#Include <StaticConstants.au3>
#Include <StructureConstants.au3>
Opt("MustDeclareVars", 0)

Global Const $AC_SRC_ALPHA = 1

Global Const $RT_ACCELERATOR = 9
Global Const $RT_ANICURSOR = 21
Global Const $RT_ANIICON = 22
Global Const $RT_BITMAP = 2
Global Const $RT_CURSOR = 1
Global Const $RT_DIALOG = 5
Global Const $RT_DLGINCLUDE = 17
Global Const $RT_FONT = 8
Global Const $RT_FONTDIR = 7
Global Const $RT_GROUP_CURSOR = 12
Global Const $RT_GROUP_ICON = 14
Global Const $RT_HTML = 23
Global Const $RT_ICON = 3
Global Const $RT_MANIFEST = 24
Global Const $RT_MENU = 4
Global Const $RT_MESSAGETABLE = 11
Global Const $RT_PLUGPLAY = 19
Global Const $RT_RCDATA = 10
Global Const $RT_STRING = 6
Global Const $RT_VERSION = 16
Global Const $RT_VXD = 20


Global $hInstance = _WinAPI_GetModuleHandle('')
_GDIPlus_Startup()
$hImage = _LoadImage('green')


$width = _GDIPlus_ImageGetWidth($hImage)
$height = _GDIPlus_ImageGetHeight($hImage)


$GUI = GUICreate("simple png", 256, 256, -1, -1, $WS_POPUP, $WS_EX_LAYERED)
SetBitmap($GUI, $hImage, 255)

GUIRegisterMsg($WM_NCHITTEST, "WM_NCHITTEST")
GUISetState()
WinSetOnTop($GUI, "", 1)
For $i = 0 To 255 Step 10
    SetBitmap($GUI, $hImage, $i)
Next


$controlGui = GUICreate("Управление", $width, $height, 0, 0, $WS_POPUP, BitOR($WS_EX_LAYERED, $WS_EX_MDICHILD), $GUI)

$pic = GUICtrlCreatePic('', 200, 231, 56, 25)
_SetImageBinaryToCtrl($pic, _LoadString('grey'))
$exButton = GUICtrlCreateButton("Выход", 200, 231, 56, 25, $BS_DEFPUSHBUTTON)
GUICtrlSetBkColor(-1, 0x00FF00)
GUISetState()


While 1
    $msg = GUIGetMsg()
    Select
        Case $msg = $GUI_EVENT_CLOSE
            ExitLoop
        Case $msg = $exButton
            ExitLoop
    EndSelect
WEnd


GUIDelete($controlGui)
For $i = 255 To 0 Step -10
    SetBitmap($GUI, $hImage, $i)
Next
_WinAPI_DeleteObject($hImage)
_GDIPlus_Shutdown()


Func WM_NCHITTEST($hWnd, $iMsg, $iwParam, $ilParam)
    If ($hWnd = $GUI) And ($iMsg = $WM_NCHITTEST) Then Return $HTCAPTION
EndFunc   ;==>WM_NCHITTEST

Func SetBitmap($hGUI, $hImage, $iOpacity)
    Local $hScrDC, $hMemDC, $hBitmap, $hOld, $pSize, $tSize, $pSource, $tSource, $pBlend, $tBlend

    $hScrDC = _WinAPI_GetDC(0)
    $hMemDC = _WinAPI_CreateCompatibleDC($hScrDC)
    $hBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage)
    $hOld = _WinAPI_SelectObject($hMemDC, $hBitmap)
    $tSize = DllStructCreate($tagSIZE)
    $pSize = DllStructGetPtr($tSize)
    DllStructSetData($tSize, "X", _GDIPlus_ImageGetWidth($hImage))
    DllStructSetData($tSize, "Y", _GDIPlus_ImageGetHeight($hImage))
    $tSource = DllStructCreate($tagPOINT)
    $pSource = DllStructGetPtr($tSource)
    $tBlend = DllStructCreate($tagBLENDFUNCTION)
    $pBlend = DllStructGetPtr($tBlend)
    DllStructSetData($tBlend, "Alpha", $iOpacity)
    DllStructSetData($tBlend, "Format", $AC_SRC_ALPHA)
    _WinAPI_UpdateLayeredWindow($hGUI, $hScrDC, 0, $pSize, $hMemDC, $pSource, 0, $pBlend, $ULW_ALPHA)
    _WinAPI_ReleaseDC(0, $hScrDC)
    _WinAPI_SelectObject($hMemDC, $hOld)
    _WinAPI_DeleteObject($hBitmap)
    _WinAPI_DeleteDC($hMemDC)
EndFunc   ;==>SetBitmap


Func _LoadImage($iRes)

	Local $hInfo, $hData, $pData, $hMem, $pMem, $iSize, $hStream, $hImage

	$hInfo = _WinAPI_FindResource($hInstance, $RT_RCDATA, $iRes)
	$hData = _WinAPI_LoadResource($hInstance, $hInfo)
	$iSize = _WinAPI_SizeOfResource($hInstance, $hInfo)
	$pData = _WinAPI_LockResource($hData)
	If @error Then
		Return 0
	EndIf
	$hMem = _MemGlobalAlloc($iSize, 2)
	$pMem = _MemGlobalLock($hMem)
	_MemMoveMemory($pData, $pMem, $iSize)
	_MemGlobalUnlock($hMem)
	$hStream = _WinAPI_CreateStreamOnHGlobal($hMem)
	$hImage = DllCall($ghGDIPDll, 'uint', 'GdipCreateBitmapFromStream', 'ptr', $hStream, 'ptr*', 0)
;	_WinAPI_FreeResource($hData)
	Return $hImage[2]
EndFunc   ;==>_LoadImage


Func _LoadString($iRes)

	Local $hInfo, $hData, $pData, $tData, $sData, $iSize

	$hInfo = _WinAPI_FindResource($hInstance, $RT_RCDATA, $iRes)
	$hData = _WinAPI_LoadResource($hInstance, $hInfo)
	$iSize = _WinAPI_SizeOfResource($hInstance, $hInfo)
	$pData = _WinAPI_LockResource($hData)
	If @error Then
		Return ''
	EndIf
	$tData = DllStructCreate('char[' & $iSize & ']', $pData)
	$sData = DllStructGetData($tData, 1)
;	_WinAPI_FreeResource($hData)
	Return $sData
EndFunc   ;==>_LoadString



;Authors: Prog@ndy, based on code by Zedna
Func _SetImageBinaryToCtrl($CtrlId, $Binary)
    Local $picdata = Binary($Binary) ; Fetch the Data
    Local $piclength = BinaryLen($picdata) ; Get Length

    Local $picstruct = DllStructCreate("byte[" & $piclength & "]")
        DllStructSetData($picstruct,1,$picdata)
        Local $picmemory = DllStructGetPtr($picstruct)
        _SetMemoryImageToCtrl($CtrlId, $picmemory, $piclength)
        DllStructSetData($picstruct,1,0)
    $picstruct = ""
EndFunc

; Authors: Zedna, based on code by Prog@ndy
Func _SetMemoryImageToCtrl($CtrlId, $Pointer, $nSize)
    Local $hData, $pData, $pStream, $pBitmap, $hBitmap
	; use GDI+ for converting to bitmap first
    $hData = _MemGlobalAlloc($nSize,2)
    $pData = _MemGlobalLock($hData)
    _MemMoveMemory($Pointer,$pData,$nSize)
    _MemGlobalUnlock($hData)
    $pStream = DllCall( "ole32.dll","int","CreateStreamOnHGlobal", "int",$hData, "long",1, "Int*",0)
    $pStream = $pStream[3]
    _GDIPlus_Startup()
    $pBitmap = DllCall($ghGDIPDll,"int","GdipCreateBitmapFromStream", "ptr",$pStream, "int*",0)
    $pBitmap = $pBitmap[2]
    $hBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($pBitmap)
    _SetBitmapToCtrl($CtrlId, $hBitmap)
    If @error Then SetError(3, 0, 0)
    _GDIPlus_BitmapDispose($pBitmap)
    _GDIPlus_Shutdown()
    _WinAPI_DeleteObject($pStream)
    _MemGlobalFree($hData)
EndFunc


Func _SetBitmapToCtrl($CtrlId, $hBitmap)
    Local Const $STM_SETIMAGE = 0x0172
    Local Const $IMAGE_BITMAP = 0
    Local Const $SS_BITMAP = 0xE
    Local Const $GWL_STYLE = -16

    Local $hWnd = GUICtrlGetHandle($CtrlId)
    If $hWnd = 0 Then Return SetError(1, 0, 0)
        ; set SS_BITMAP style to control
    Local $oldStyle = DllCall("user32.dll", "long", "GetWindowLong", "hwnd", $hWnd, "int", $GWL_STYLE)
    If @error Then Return SetError(2, 0, 0)
    DllCall("user32.dll", "long", "SetWindowLong", "hwnd", $hWnd, "int", $GWL_STYLE, "long", BitOR($oldStyle[0], $SS_BITMAP))
    If @error Then Return SetError(3, 0, 0)
        Local $oldBmp = DllCall("user32.dll", "hwnd", "SendMessage", "hwnd", $hWnd, "int", $STM_SETIMAGE, "int", $IMAGE_BITMAP, "int", $hBitmap)
    If @error Then Return SetError(4, 0, 0)
    If $oldBmp[0] <> 0 Then _WinAPI_DeleteObject($oldBmp[0])
    Return 1
EndFunc

читал, что такие вещи делаются путем перерисовки например "кнопки" поверх "формы окна", а как тогда задать область нажатия?
подскажите, кто сталкивался с таким :smile:
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Вариант 1.

Создаете окно-подложку из PNG файла, поверх которой располагаете дочернее окно прямоугольной формы с частью изображения подложки. В этом же окне создаете все элементы GUI. Просто и изящно.

http://autoit-script.ru/index.php?topic=5090.0

Вариант 2.

GUI состоит из одного PNG, на котором вы динамически отрисовываете все необходимые элементы в виде отдельных изображений, в данном случае кнопки. Этот вариант немного сложнее, т.к. придется писать алгоритм взаимодействия элементов GUI с пользователем, но он дает возможность изменять внешний вид не только основного окна, но и всех его элементов. Простого законченного примера на форуме нет, но вы можете взять все необходимое здесь. Так же есть Skin UDF для создания кнопок из готовых изображений, но он предназначен для работы с обычными окнами. Тем не менее, его можно легко адаптировать для работы с многослойными (layered) окнами.
 
Верх