Что нового

Создание прозрачной иконки внутри таба

CreatoR

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

Вот пример:

Код:
#include <GUIConstantsEx.au3>

$hGUI = GUICreate("Test Script", 300, 200)

$nTab = GUICtrlCreateTab(20, 10, 260, 180)
$nTabItem = GUICtrlCreateTabItem("Item")

GUICtrlCreateIcon('Setupapi.dll', -3, 40, 50)

GUISetState(@SW_SHOW, $hGUI)

While 1
	Switch GUIGetMsg()
		Case $GUI_EVENT_CLOSE
			Exit
	EndSwitch
WEnd


Вот так оно у меня выглядит:
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
madmasles сказал(а):

Не совсем (см. ниже).

:smile:

CreatoR

Меня мучает этот вопрос с самого начала знакомства с AutoIt. И знаешь, самое интересное, это как раз то, что проще всего изменить цвет Tab'а, или вообще не использовать иконки на Tab'ах. Все остальное, это шаманство. Вообщем, вот три наиболее "простых" способа решения данной проблемы.


Способ 1 (заменяем обработчик AutoIt)

Это наиболее правильный способ, здесь мы делаем именно то, что должен был делать AutoIt.

Код:
#Include <Constants.au3>
#Include <GUIConstantsEx.au3>
#Include <WinAPIEx.au3>
#Include <WindowsConstants.au3>

$hGUI = GUICreate('Test Script', 300, 200)

$nTab = GUICtrlCreateTab(20, 10, 260, 180)
$nTabItem = GUICtrlCreateTabItem('Item')

; --------------------------------------------------

$Width = 32
$Height = 32
$hIcon = _WinAPI_ShellExtractIcon(@SystemDir & '\setupapi.dll', -3, $Width, $Height)
$Label = GUICtrlCreateLabel('', 40, 50, $Width, $Height)
GUICtrlSetBkColor(-1, $GUI_BKCOLOR_TRANSPARENT)
$hLabel = GUICtrlGetHandle(-1)
$hDll = DllCallbackRegister('_WinProc', 'ptr', 'hwnd;uint;wparam;lparam')
$pDll = DllCallbackGetPtr($hDll)
$hProc = _WinAPI_SetWindowLongEx($hLabel, $GWL_WNDPROC, $pDll)
If Not $hProc Then
	DllCallbackFree($hDll)
EndIf

OnAutoItExitRegister('AutoItExit')

; --------------------------------------------------

GUISetState(@SW_SHOW, $hGUI)

While 1
	Switch GUIGetMsg()
		Case $GUI_EVENT_CLOSE
			Exit
	EndSwitch
WEnd

Func _WinProc($hWnd, $iMsg, $wParam, $lParam)
	Switch $iMsg
		Case $WM_PAINT

			Local $hDC, $tPAINTSTRUCT

			$hDC = _WinAPI_BeginPaint($hWnd, $tPAINTSTRUCT)
			_WinAPI_DrawIconEx($hDC, 0, 0, $hIcon, $Width, $Height)
			_WinAPI_EndPaint($hWnd, $tPAINTSTRUCT)
			Return 0
	EndSwitch
	Return _WinAPI_CallWindowProc($hProc, $hWnd, $iMsg, $wParam, $lParam)
EndFunc   ;==>_WinProc

Func AutoItExit()
	If $hProc Then
		_WinAPI_SetWindowLongEx($hLabel, $GWL_WNDPROC, $hProc)
		DllCallbackFree($hDll)
	EndIf
EndFunc   ;==>AutoItExit


Способ 2 (Icons.au3)

Здесь проблема в том, что полупрозрачные иконки будут имень "темный налет" (дело в том, что эта библиотека писалась для максимальной интеграции в AutoIt, т.е. для новичков, и все, что можно было сделать, я сделал).

Код:
#Include <GUIConstantsEx.au3>
#Include <Icons.au3>
#Include <WinAPI.au3>

$hGUI = GUICreate('Test Script', 300, 200)

$nTab = GUICtrlCreateTab(20, 10, 260, 180)
$nTabItem = GUICtrlCreateTabItem('Item')

; --------------------------------------------------

$Width = 32
$Height = 32
$hIcon = _Icons_Icon_Extract(@SystemDir & '\setupapi.dll', -3, $Width, $Height)
$hBitmap = _Icons_Bitmap_CreateFromIcon($hIcon)
$Pic = GUICtrlCreatePic('', 40, 50, $Width, $Height)
_SetHImage(-1, $hBitmap)
_WinAPI_DeleteObject($hBitmap)
_WinAPI_DestroyIcon($hIcon)

; --------------------------------------------------

GUISetState(@SW_SHOW, $hGUI)

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
    EndSwitch
WEnd


Способ 3 (Icons.au3 + WS_EX_LAYERED)

Здесь придется самому контролировать показ/скрытие иконок при переключении Tab'ов + много кода.

Код:
#Include <GUIConstantsEx.au3>
#Include <Icons.au3>
#Include <WinAPIEx.au3>
#Include <WindowsConstants.au3>

$hGUI = GUICreate('Test Script', 300, 200)

$nTab = GUICtrlCreateTab(20, 10, 260, 180)
$nTabItem = GUICtrlCreateTabItem('Item')

; --------------------------------------------------

$X = 40
$Y = 50
$Width = 32
$Height = 32
$hIcon = _WinAPI_ShellExtractIcon(@SystemDir & '\setupapi.dll', -3, $Width, $Height)
$hBitmap = _Icons_Bitmap_CreateFromIcon($hIcon)
$Pos = _WinGetClientPos($hGUI)
$hParent = GUICreate('', $Width, $Height, $Pos[0] + $X, $Pos[1] + $Y, BitOR($WS_DISABLED, $WS_POPUPWINDOW), $WS_EX_LAYERED, $hGUI)
_WinAPI_UpdateLayeredWindowEx($hParent, $hBitmap, 255, 1)
_WinAPI_DestroyIcon($hIcon)

GUIRegisterMsg($WM_MOVE, 'WM_MOVE')

; --------------------------------------------------

GUISetState(@SW_SHOW, $hGUI)
GUISetState(@SW_SHOW, $hParent)

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
    EndSwitch
WEnd

Func _WinGetClientPos($hWnd)

    Local $Size = WinGetClientSize($hWnd)

    If Not IsArray($Size) Then
        Return SetError(1, 0, 0)
    EndIf

    Local $tPOINT = DllStructCreate($tagPOINT)

    For $i = 1 To 2
        DllStructSetData($tPOINT, $i, 0)
    Next
    _WinAPI_ClientToScreen($hWnd, $tPOINT)
    If @error Then
        Return SetError(1, 0, 0)
    EndIf

    Local $Pos[4]

    For $i = 0 To 1
        $Pos[$i] = DllStructGetData($tPOINT, $i + 1)
    Next
    For $i = 2 To 3
        $Pos[$i] = $Size[$i - 2]
    Next
    Return $Pos
EndFunc   ;==>_WinGetClientPos

Func WM_MOVE($hWnd, $iMsg, $wParam, $lParam)

    Local $Xi = BitAND($lParam, 0xFFFF), $Yi = BitShift($lParam, 16)

    If $Xi > 0x7FFF Then
        $Xi -= 0x10000
    EndIf
    If $Yi > 0x7FFF Then
        $Yi -= 0x10000
    EndIf
    Switch $hWnd
        Case 0

        Case $hGUI
            WinMove($hParent, '', $X + $Xi, $Y + $Yi)
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_MOVE


Можно еще определить цвета градиента Tab'а в том месте, где находится иконка, с помощью функции _WinAPI_GetThemeColor(), нарисовать его и подложить под иконку. Затем полученный bitmap вставить в Pic. Но проблема в том, что некоторые "левые" темы оформления Windows могут возвращать неправильные цвета Tab'ов и других элементов GUI. Я думаю именно поэтому ты не хочешь изменять цвет Tab'ов?

Вообщем, выбирай.

:smile:

Используемые библиотеки: Icons.au3, WinAPIEx.au3
 
Автор
CreatoR

CreatoR

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

Так что остановимся на этом методе, он проще всех, если будут проблемы, возьму первый :smile:

Спасибо.
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
CreatoR сказал(а):
...никакого налёта я не замечаю.

Ух е... Действительно нет, а если файл брать из, например, PNG, то есть... Да, классный UDF все-таки получился.

:laugh:
 

Garrett

Модератор
Локальный модератор
Сообщения
3,999
Репутация
967
Yashied [?]
а если файл брать из, например, PNG
Да, формат PNG он такой, непредсказуемый! ;D
У меня даже просто при работе с ним в Photoshop`e возникали непредсказуемые ситуации!
 

saavaage

Знающий
Сообщения
171
Репутация
17
Здравствуйте, попробовал применить 2-ой способ по работе с иконками.
Получился такой скрипт:

Код:
#include <ButtonConstants.au3>
#include <Constants.au3>
#include <GUIConstantsEx.au3>
#include <Icons.au3>
#include <WinAPI.au3>


; Hotfixes
Global $pic1_1, $sLogI1_1
Global $sLog1_1

Opt("GUIOnEventMode", 1)

$hMain_GUI = GUICreate("Диагностика и Настройка", 619, 442, 189, 122)
GUISetOnEvent($GUI_EVENT_CLOSE, "CLOSEClicked")

$Tab1 = GUICtrlCreateTab(8, 16, 601, 377)

;;;; Hotfixes ;;;;
$HotfixErrors = GUICtrlCreateTabItem("HotfixErrors")

GUICtrlCreateGroup("Службы, отвечающие за Автообновление", 16, 330, 370, 55)

GUICtrlCreateLabel("Автоматич. обновление", 24, 348, 75, 30, $BS_MULTILINE)
GUICtrlCreateLabel("тс", 95, 348, 15, 15)

_ServicesStat(); запуск и сбор информации о текущем состоянии служб


$Button_StartOptim = GUICtrlCreateButton("Старт", 478, 342, 55, 35, $BS_MULTILINE)
GUICtrlSetOnEvent($Button_StartOptim, "_StartOptim")

;;; Devices ;;;
$DevicesErrors = GUICtrlCreateTabItem("DriversErrors")
GUICtrlCreateGroup("Список проблемного оборудования", 16, 48, 481, 337)

GUICtrlCreateTabItem("")

GUISetState()

While 1
    Sleep(100)
WEnd


Func CLOSEClicked()
  Exit
EndFunc


; функция оптимизации настроек служб для запуска и работы MU
Func _StartOptim()
	GUICtrlSetState($Button_StartOptim, $GUI_DISABLE)
	Run('sc start wuauserv', '', @SW_HIDE)
	sleep(1000)
   _ServicesStat(); обновление иформации и иконки
     sleep(1000)
   GUICtrlSetState($Button_StartOptim, $GUI_ENABLE)
EndFunc

Func _ServicesStat()

  $sLog1_1 = ''

;  запрос информации о состоянии служб (текущее состояние: работает или нет)
 $hIPconfig1_1 = Run('sc query wuauserv', '', @SW_HIDE, $STDOUT_CHILD)

 While 1
    $sLogI1_1 &= StdoutRead($hIPconfig1_1)

	If @error Then ExitLoop
    Sleep(10)
 WEnd

; фильтрация информации о службах
  $sLog1_1 = StringRegExpReplace($sLogI1_1, "(?si).*STATE\D*(\d+).*", '\1')
; программиорование отображение информации о службах через иконки
Dim $aIcons[2]=['error.ico','ok.ico']
$pic1_1=$aIcons[$sLog1_1=4]
 _ImageGet()

EndFunc

; функция отображения иконок на конкрентой вкладке формы (форма с Tab)
Func _ImageGet()
$Width = 14
$Height = 14
$hIcon1_1 = _Icons_Icon_Extract($pic1_1, -3, $Width, $Height)
$hBitmap1_1 = _Icons_Bitmap_CreateFromIcon($hIcon1_1)
$Pic1_1 = GUICtrlCreatePic('', 115, 348, $Width, $Height)
_SetHImage(-1, $hBitmap1_1)

_WinAPI_DeleteObject($hBitmap1_1)
_WinAPI_DestroyIcon($hIcon1_1)

EndFunc

Проблема в следующем: У меня по умолчанию отключена служба Автообновления, что соответствует красной иконке напротив "тс". Когда я нажимаю на кнопку "Старт" (происходит запуск службы Автообновления) иконка с красной меняется на зеленую на вкладке Hotfixes. К сожалению после этого действия иконка "прорисовывается" на всех вкладках утилиты, а не только Hotfixes. Как это можно побороть? Помогите, плиз.

PS Иконки и функцию прикрепил в архиве. версия autoit 3.3.6.1
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
При каждом нажатии на кнопку "Старт", вызывается GUICtrlCreatePic()...

;)
 

saavaage

Знающий
Сообщения
171
Репутация
17
Это я понял. Только как можно это обойти? В ней же нельзя указать конкретную ID. Можете подсказать, что делать? Уже 2-ой день вокруг "хожу", как кот вокруг тарелки со сметаной...

GUICtrlSetImage ?
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
saavaage сказал(а):
Это я понял. Только как можно это обойти? В ней же нельзя указать конкретную ID. Можете подсказать, что делать? Уже 2-ой день вокруг "хожу", как кот вокруг тарелки со сметаной...

В _SetHImage() можно передать как хендл, так и ID или (-1).

Код:
#include <ButtonConstants.au3>
#include <Constants.au3>
#include <GUIConstantsEx.au3>
#include <Icons.au3>
#include <WinAPI.au3>


; Hotfixes
Global $Pic, $hIcon, $Width = 14, $Height = 14
Global $aIcons[2] = ['error.ico', 'ok.ico']
Global $sLogI1_1, $sLog1_1

For $i = 0 To 1
	$hIcon = _Icons_Icon_Extract($aIcons[$i], 0, $Width, $Height)
	$aIcons[$i] = _Icons_Bitmap_CreateFromIcon($hIcon)
	_WinAPI_DestroyIcon($hIcon)
Next

Opt("GUIOnEventMode", 1)

$hMain_GUI = GUICreate("Диагностика и Настройка", 619, 442, 189, 122)
GUISetOnEvent($GUI_EVENT_CLOSE, "CLOSEClicked")

$Tab1 = GUICtrlCreateTab(8, 16, 601, 377)

;;;; Hotfixes ;;;;
$HotfixErrors = GUICtrlCreateTabItem("HotfixErrors")

GUICtrlCreateGroup("Службы, отвечающие за Автообновление", 16, 330, 370, 55)

GUICtrlCreateLabel("Автоматич. обновление", 24, 348, 75, 30, $BS_MULTILINE)
GUICtrlCreateLabel("тс", 95, 348, 15, 15)

$Pic = GUICtrlCreatePic('', 115, 348, $Width, $Height)

_ServicesStat(); запуск и сбор информации о текущем состоянии служб

$Button_StartOptim = GUICtrlCreateButton("Старт", 478, 342, 55, 35, $BS_MULTILINE)
GUICtrlSetOnEvent($Button_StartOptim, "_StartOptim")

;;; Devices ;;;
$DevicesErrors = GUICtrlCreateTabItem("DriversErrors")
GUICtrlCreateGroup("Список проблемного оборудования", 16, 48, 481, 337)

GUICtrlCreateTabItem("")

GUISetState()

While 1
	Sleep(100)
WEnd


Func CLOSEClicked()
	Exit
EndFunc   ;==>CLOSEClicked


; функция оптимизации настроек служб для запуска и работы MU
Func _StartOptim()
	GUICtrlSetState($Button_StartOptim, $GUI_DISABLE)
	Run('sc start wuauserv', '', @SW_HIDE)
	Sleep(1000)
	_ServicesStat(); обновление иформации и иконки
	Sleep(1000)
	GUICtrlSetState($Button_StartOptim, $GUI_ENABLE)
EndFunc   ;==>_StartOptim

Func _ServicesStat()

	$sLog1_1 = ''

	;  запрос информации о состоянии служб (текущее состояние: работает или нет)
	$hIPconfig1_1 = Run('sc query wuauserv', '', @SW_HIDE, $STDOUT_CHILD)

	While 1
		$sLogI1_1 &= StdoutRead($hIPconfig1_1)

		If @error Then ExitLoop
		Sleep(10)
	WEnd

	; фильтрация информации о службах
	$sLog1_1 = StringRegExpReplace($sLogI1_1, "(?si).*STATE\D*(\d+).*", '\1')

	_SetHImage($Pic, $aIcons[$sLog1_1 = 4])

EndFunc   ;==>_ServicesStat
 
Верх