Что нового

Элементы GUI Тематическая кнопка на восемь состояний

musicstashall

Новичок
Хочу создать стилизованную по классу из визуального стиля кнопку Pause/Continue, не знаю как задействовать вторую четверку изображений для состояния. В визуальном стиле используется лента из восьми изображений — четыре на отображение состояния паузы и четыре на отображение состояния продолжения. В следующем примере кнопка отображает только первые четыре изображения — состояние паузы. Как задействовать вторую четверку изображений?

Код:
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
#include <GuiButton.au3>
#include <WinAPITheme.au3>
#include <GuiImageList.au3>

Local $GUI = GUICreate('', 200, 100)

Local $but = GUICtrlCreateButton('', 50, 50, 17, 16) ;_GUICtrlButton_Create($GUI, '', 50, 50, 17, 16)

_Winapi_SetWindowTheme(GUICtrlGetHandle($but), '', 'Pause')
GUISetState()
Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE

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

Получилось только сложным путем, рисовать с помощью _WinAPI_DrawThemeBackground

Код:
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
#include <WinAPITheme.au3>
#include <WinAPIGdi.au3>
#include <WinAPISysWin.au3>


Local $GUI = GUICreate('', 200, 100)

Local $but = GUICtrlCreatePic('', 50, 50, 17, 16)
_GUICtrlSetTheme(-1, 'Pause', 1, 1, 17, 16)
GUISetState()

For $i = 1 To 8
   _GUICtrlSetTheme($but, 'Pause', 1, $i, 17, 16)
   Sleep(1000)
Next

;Do
;Until GUIGetMsg() = $GUI_EVENT_CLOSE

Func _GUICtrlSetTheme($CTRL, $Class, $Part, $Stat, $width, $height)
    Local $hCTRL = GUICtrlGetHandle($CTRL)
    Local $hDev = _WinAPI_GetDC($hCTRL)
    Local $hDC = _WinAPI_CreateCompatibleDC($hDev)
    Local $hSource = _WinAPI_CreateCompatibleBitmapEx($hDev, $width, $height, _WinAPI_SwitchColor(_WinAPI_GetSysColor($COLOR_3DFACE)))
    Local $hSv = _WinAPI_SelectObject($hDC, $hSource)
    Local $tRECT = _WinAPI_CreateRectEx(0, 0, $width, $height)
    Local $hTheme = _WinAPI_OpenThemeData(0, $Class)
    _WinAPI_DrawThemeBackground($hTheme, $Part, $Stat, $hDC, $tRECT)
    _WinAPI_CloseThemeData($hTheme)
    Local $hBitmap = _WinAPI_CreateCompatibleBitmap($hDev, $width, $height)
    _WinAPI_SelectObject($hDC, $hBitmap)
    _WinAPI_DrawBitmap($hDC, 0, 0, $hSource, $MERGECOPY)
    _WinAPI_ReleaseDC($hCTRL, $hDev)
    _WinAPI_DeleteObject($hSource)
    _WinAPI_DeleteDC($hDC)
    _WinAPI_DeleteObject(_SendMessage($hCTRL, $STM_SETIMAGE, 0, $hBitmap))
    Local $hWnd = _WinAPI_GetAncestor($hCTRL, $GA_ROOT)
    Local $Pos = ControlGetPos($hWnd, '', $hCTRL)
    If @error Then Return
    _WinAPI_InvalidateRect($hWnd, _WinAPI_CreateRectEx($pos[0], $pos[1], $width, $height), True)
EndFunc
 

Вложения

Последнее редактирование:

joiner

Модератор
Локальный модератор
думаю, что контролируемый способ лучше. то есть, вариант с функцией. а просто подставлять картинки-иконки не подходит?
 
Автор
M

musicstashall

Новичок
просто подставлять картинки-иконки не подходит?
Тут рисуется именно тема кнопки, с использованием Margins параметров растяжения, с учетом размеров также параметр DPI, просто так взять картинку и впихнуть ее в Pic, не всегда даст нужный результат. Меня другое смущает — фон рисуется прозрачным (за кнопкой просвечивает задний фон). То есть, если применить к окну BlurBehind, то контрол просвечивает, получается не как настоящая кнопка, а как простой рисунок на окне. Попробую с помощью GDIP рисовать.
 
Последнее редактирование:

Tempo

Скриптер
получается не как настоящая кнопка
Если вам нужна обычная кнопка с изображением, тогда почему просто не использовать кнопку со своим списком изображений?

Пример
Код:
;~ AutoIt Version:    3.3.14.5
;~ Author:            Tempo
#include <GUIConstants.au3>
#include <GuiButton.au3>
#include <GuiImageList.au3>
#include <GDIPlus.au3>

Example()

Func Example()
    _GDIPlus_Startup()

    GUICreate(@ScriptName, 400, 400)

    Local Const $ICON_SIZE = 24
    Local Const $BUTTON_SIZE = $ICON_SIZE * 2

    Local $iY = 10
    Local $idBtnPlay = GUICtrlCreateButton("", 10, $iY, $BUTTON_SIZE, $BUTTON_SIZE)
    $iY += $BUTTON_SIZE + 10
    Local $idBtnPause = GUICtrlCreateButton("", 10, $iY, $BUTTON_SIZE, $BUTTON_SIZE)
    $iY += $BUTTON_SIZE + 10
    Local $idBtnPlayPause = GUICtrlCreateButton("", 10, $iY, $BUTTON_SIZE, $BUTTON_SIZE)

    Local $aColors[6]
    $aColors[0] = _WinAPI_GetSysColor($COLOR_WINDOWTEXT)
    $aColors[1] = _WinAPI_GetSysColor($COLOR_HIGHLIGHT)
    $aColors[2] = _WinAPI_InvertColor($aColors[1])
    $aColors[3] = _WinAPI_GetSysColor($COLOR_GRAYTEXT)
    $aColors[4] = $aColors[0]
    $aColors[5] = $aColors[1]
    For $i = 0 To UBound($aColors) - 1
        $aColors[$i] = BitOR(0xFF000000, _WinAPI_SwitchColor($aColors[$i]))
    Next

    Local $aPointsPlay[][] = [[0], [0, 0], [0, $ICON_SIZE], [$ICON_SIZE, $ICON_SIZE / 2]]
    $aPointsPlay[0][0] = UBound($aPointsPlay) - 1

    Local $aPointsPause[][] = [[0], [0, 0], [0, $ICON_SIZE], [$ICON_SIZE * 0.375, $ICON_SIZE], [$ICON_SIZE * 0.375, 0], _
            [$ICON_SIZE * 0.625, 0], [$ICON_SIZE * 0.625, $ICON_SIZE], [$ICON_SIZE, $ICON_SIZE], [$ICON_SIZE, 0]]
    $aPointsPause[0][0] = UBound($aPointsPause) - 1

    Local $hImageListPlay = ImageListFromPolygon($aColors, $aPointsPlay, $ICON_SIZE, $ICON_SIZE)
    Local $hImageListPause = ImageListFromPolygon($aColors, $aPointsPause, $ICON_SIZE, $ICON_SIZE)
    _GUICtrlButton_SetImageList($idBtnPlay, $hImageListPlay, 4)
    _GUICtrlButton_SetImageList($idBtnPlayPause, $hImageListPlay, 4)
    _GUICtrlButton_SetImageList($idBtnPause, $hImageListPause, 4)

    GUISetState()

    Local $aImageListInfo
    While 1
        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE
                ExitLoop
            Case $idBtnPlay
                GUICtrlSetState($idBtnPlay, $GUI_DISABLE)
                GUICtrlSetState($idBtnPause, $GUI_ENABLE)
            Case $idBtnPause
                GUICtrlSetState($idBtnPlay, $GUI_ENABLE)
                GUICtrlSetState($idBtnPause, $GUI_DISABLE)
            Case $idBtnPlayPause
                $aImageListInfo = _GUICtrlButton_GetImageList($idBtnPlayPause)
                _GUICtrlButton_SetImageList($idBtnPlayPause, _
                        ($aImageListInfo[0] = $hImageListPlay ? $hImageListPause : $hImageListPlay), _
                        $aImageListInfo[5], _
                        $aImageListInfo[1], _
                        $aImageListInfo[2], _
                        $aImageListInfo[3], _
                        $aImageListInfo[4])
        EndSwitch
    WEnd
EndFunc   ;==>Example

Func ImageListFromPolygon(Const ByRef $aColors, Const ByRef $aPoints, $iWidth, $iHeight)
    Local $hImageList = _GUIImageList_Create($iWidth, $iHeight, 5)
    Local $hBitmap, $hGraphics, $hBrush
    For $i = 0 To UBound($aColors) - 1
        $hBitmap = _GDIPlus_BitmapCreateFromScan0($iWidth, $iHeight)
        $hGraphics = _GDIPlus_ImageGetGraphicsContext($hBitmap)
        _GDIPlus_GraphicsSetSmoothingMode($hGraphics, $GDIP_SMOOTHINGMODE_HIGHQUALITY)
        _GDIPlus_GraphicsSetPixelOffsetMode($hGraphics, $GDIP_PIXELOFFSETMODE_HIGHQUALITY)
        $hBrush = _GDIPlus_BrushCreateSolid($aColors[$i])
        _GDIPlus_GraphicsFillPolygon($hGraphics, $aPoints, $hBrush)
        _GUIImageList_Add($hImageList, _GDIPlus_BitmapCreateDIBFromBitmap($hBitmap))
        _GDIPlus_BrushDispose($hBrush)
        _GDIPlus_GraphicsDispose($hGraphics)
        _GDIPlus_BitmapDispose($hBitmap)
    Next
    Return $hImageList
EndFunc   ;==>ImageListFromPolygon


Тут рисуется именно тема кнопки, с использованием Margins параметров растяжения, с учетом размеров также параметр DPI
Надеюсь вы это проверили.
 
Последнее редактирование:
Автор
M

musicstashall

Новичок
Надеюсь вы это проверили.
Естественно. Дело даже не только в кнопке, а вообще любого фона, определяющегося в визуальном стиле. Например, изображение представляет из себя всего два пикселя и растягивается с отступом в пиксель. Это означает, что по вертикали (или по горизонтали) один пиксель не растягивается, а растягиваются остальные пиксели.

Если вам нужна обычная кнопка с изображением, тогда почему просто не использовать кнопку со своим списком изображений?
Молодец, красиво сделал. Но где в этом примере тематическая кнопка?? Где, собственно, визуальный стиль? В теме обсуждается именно стиль, определенный в классе визуального стиля.
 
Автор
M

musicstashall

Новичок
Смысл как раз в том, чтобы использовать стиль.
Сообщение автоматически объединено:

Давай попробуем такую кнопочку нарисовать:
Код:
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
#include <WinAPITheme.au3>
#include <WinAPIGdi.au3>
#include <WinAPISysWin.au3>

Local $hTheme = _WinAPI_OpenThemeData(0, 'TaskDialog')
Global $ExpandedButWidth = _WinAPI_GetThemeInt($hTheme, 13, 0, $TMT_WIDTH)
Global $ExpandedButHeight = _WinAPI_GetThemeInt($hTheme, 13, 0, $TMT_HEIGHT)
_WinAPI_CloseThemeData($hTheme)

Local $GUI = GUICreate('', 200, 100)

Local $but = GUICtrlCreatePic('', 50, 50, $ExpandedButWidth, $ExpandedButHeight)
_GUICtrlSetTheme(-1, 'TaskDialog', 13, 1, $ExpandedButWidth, $ExpandedButHeight)
GUISetState()

For $i = 1 To 6
   _GUICtrlSetTheme($but, 'TaskDialog', 13, $i, $ExpandedButWidth, $ExpandedButHeight)
   Sleep(1000)
Next

;Do
;Until GUIGetMsg() = $GUI_EVENT_CLOSE

Func _GUICtrlSetTheme($CTRL, $Class, $Part, $Stat, $width, $height)
    Local $hCTRL = GUICtrlGetHandle($CTRL)
    Local $hDev = _WinAPI_GetDC($hCTRL)
    Local $hDC = _WinAPI_CreateCompatibleDC($hDev)
    Local $hSource = _WinAPI_CreateCompatibleBitmapEx($hDev, $width, $height, _WinAPI_SwitchColor(_WinAPI_GetSysColor($COLOR_3DFACE)))
    Local $hSv = _WinAPI_SelectObject($hDC, $hSource)
    Local $tRECT = _WinAPI_CreateRectEx(0, 0, $width, $height)
    Local $hTheme = _WinAPI_OpenThemeData(0, $Class)
    _WinAPI_DrawThemeBackground($hTheme, $Part, $Stat, $hDC, $tRECT)
    _WinAPI_CloseThemeData($hTheme)
    Local $hBitmap = _WinAPI_CreateCompatibleBitmap($hDev, $width, $height)
    _WinAPI_SelectObject($hDC, $hBitmap)
    _WinAPI_DrawBitmap($hDC, 0, 0, $hSource, $MERGECOPY)
    _WinAPI_ReleaseDC($hCTRL, $hDev)
    _WinAPI_DeleteObject($hSource)
    _WinAPI_DeleteDC($hDC)
    _WinAPI_DeleteObject(_SendMessage($hCTRL, $STM_SETIMAGE, 0, $hBitmap))
    Local $hWnd = _WinAPI_GetAncestor($hCTRL, $GA_ROOT)
    Local $Pos = ControlGetPos($hWnd, '', $hCTRL)
    If @error Then Return
    _WinAPI_InvalidateRect($hWnd, _WinAPI_CreateRectEx($pos[0], $pos[1], $width, $height), True)
EndFunc

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

А вот рисуется нижний бар, такой как в панели инструментов. Здесь как раз демонстрируется растяжение пикселов:

Код:
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
#include <WinAPITheme.au3>
#include <WinAPIGdi.au3>
#include <WinAPISysWin.au3>

Local $hTheme = _WinAPI_OpenThemeData(0, 'TaskDialog')
Global $ExpandedButWidth = _WinAPI_GetThemeInt($hTheme, 13, 0, $TMT_WIDTH)
Global $ExpandedButHeight = _WinAPI_GetThemeInt($hTheme, 13, 0, $TMT_HEIGHT)
_WinAPI_CloseThemeData($hTheme)
Local $hTheme = _WinAPI_OpenThemeData(0, 'ControlPanel')
Global $BAR_COLOR = _WinAPI_GetThemeColor($hTheme, 12, 0, $TMT_FILLCOLORHINT)
_WinAPI_CloseThemeData($hTheme)

Local $GUI = GUICreate('', 200, 100)
GUISetBkColor(_WinAPI_SwitchColor(_WinAPI_GetSysColor($COLOR_WINDOW)))
GUICtrlCreatePic('', 0, 65, 200, 45)
_GUICtrlSetTheme(-1, 'ControlPanel', 12, 0, 200, 45, $BAR_COLOR)
Local $but = GUICtrlCreatePic('', 50, 20, $ExpandedButWidth, $ExpandedButHeight)
_GUICtrlSetTheme(-1, 'TaskDialog', 13, 1, $ExpandedButWidth, $ExpandedButHeight)
GUISetState()

For $i = 1 To 8
   _GUICtrlSetTheme($but, 'TaskDialog', 13, $i, $ExpandedButWidth, $ExpandedButHeight)
   Sleep(1000)
Next

;Do
;Until GUIGetMsg() = $GUI_EVENT_CLOSE

Func _GUICtrlSetTheme($CTRL, $Class, $Part, $Stat, $width, $height, $aColor = _WinAPI_SwitchColor(_WinAPI_GetSysColor($COLOR_3DFACE)))
    Local $hCTRL = GUICtrlGetHandle($CTRL)
    Local $hDev = _WinAPI_GetDC($hCTRL)
    Local $hDC = _WinAPI_CreateCompatibleDC($hDev)
    Local $hSource = _WinAPI_CreateCompatibleBitmapEx($hDev, $width, $height, $aColor)
    Local $hSv = _WinAPI_SelectObject($hDC, $hSource)
    Local $tRECT = _WinAPI_CreateRectEx(0, 0, $width, $height)
    Local $hTheme = _WinAPI_OpenThemeData(0, $Class)
    _WinAPI_DrawThemeBackground($hTheme, $Part, $Stat, $hDC, $tRECT)
    _WinAPI_CloseThemeData($hTheme)
    Local $hBitmap = _WinAPI_CreateCompatibleBitmap($hDev, $width, $height)
    _WinAPI_SelectObject($hDC, $hBitmap)
    _WinAPI_DrawBitmap($hDC, 0, 0, $hSource, $MERGECOPY)
    _WinAPI_ReleaseDC($hCTRL, $hDev)
    _WinAPI_DeleteObject($hSource)
    _WinAPI_DeleteDC($hDC)
    _WinAPI_DeleteObject(_SendMessage($hCTRL, $STM_SETIMAGE, 0, $hBitmap))
    Local $hWnd = _WinAPI_GetAncestor($hCTRL, $GA_ROOT)
    Local $Pos = ControlGetPos($hWnd, '', $hCTRL)
    If @error Then Return
    _WinAPI_InvalidateRect($hWnd, _WinAPI_CreateRectEx($pos[0], $pos[1], $width, $height), True)
EndFunc
 
Последнее редактирование:
Верх