Что нового

Получение иконки из полотна по таблице

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Вот такая вот интересная задачка:

Имеется файл полотна иконок:


Нужна функция извлечения (в итоге будет помещено в ImageList) иконок по таблице.
К примеру, передаём функции строку RU (R сверху из колонок, и U слева из строк), она возвращает иконку флага России.

:scratch:

С такой таблицей станет довольно просто использовать иконки флагов разных стран.
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
CreatoR,
Можно так сделать:
Код:
#include <StaticConstants.au3>
#include <GUIConstantsEx.au3>
#include <GDIPlus.au3>
#include <GuiListView.au3>
#include <GuiImageList.au3>

Opt('MustDeclareVars', 1)

_Example_1('NR')
_Example_2()
_Example_3()

Func _Example_3()
	Local $a_Country[26 ^ 2], $i_Ind, $s_Chr, $h_Gui, $h_IL, $h_HBitmap, $h_ListView, $s_TD

	For $i = 0 To 25
		$s_Chr = Chr($i + 65)
		For $j = 0 To 25
			$a_Country[$i_Ind] = $s_Chr & Chr($j + 65)
			$i_Ind += 1
		Next
	Next
	$s_Chr = ''
	$i_Ind = 0
	$h_IL = _GUIImageList_Create(16, 11, 5)
;~ 	---
	Local $i_Timer = TimerInit()
;~ 	---
	For $i = 0 To UBound($a_Country) - 1
		$h_HBitmap = _GetCountryFlagHBitmapString($a_Country[$i])
		If @error Then Return ConsoleWrite('! Error' & @LF)
		_GUIImageList_Add($h_IL, $h_HBitmap)
		_WinAPI_DeleteObject($h_HBitmap)
	Next
	$s_TD = StringFormat('TimerDiff: %d msec', Round(TimerDiff($i_Timer)))
	$h_HBitmap = 0
	$h_Gui = GUICreate('Example_2', 250, 270)
	GUICtrlCreateLabel($s_TD, 5, 5, 240, 20, BitOR($GUI_SS_DEFAULT_LABEL, $SS_CENTER, $SS_CENTERIMAGE))
	$h_ListView = GUICtrlCreateListView('', 10, 30, 230, 230)
	_GUICtrlListView_SetImageList($h_ListView, $h_IL, 1)
	_GUICtrlListView_AddColumn($h_ListView, 'Country', 200)
	For $i = 0 To UBound($a_Country) - 1
		_GUICtrlListView_AddItem($h_ListView, $a_Country[$i], $i)
	Next
	$a_Country = 0
	GUISetState()
	While 1
		Switch GUIGetMsg()
			Case $GUI_EVENT_CLOSE
				ExitLoop
		EndSwitch
	WEnd
	_GUIImageList_Destroy($h_IL)
	GUIDelete()
EndFunc   ;==>_Example_3

Func _Example_2()
	Local $a_Country[11] = ['BA', 'MA', 'GB', 'IL', 'FO', 'PY', 'MO', 'NL', 'RU', 'KZ', 'ZZ'], $h_Gui, $h_IL, $h_HBitmap, $h_ListView, $s_TD

	$h_IL = _GUIImageList_Create(16, 11, 5)
;~ 	---
	Local $i_Timer = TimerInit()
;~ 	---
	For $i = 0 To UBound($a_Country) - 1
		$h_HBitmap = _GetCountryFlagHBitmapString($a_Country[$i])
		If @error Then Return ConsoleWrite('! Error' & @LF)
		_GUIImageList_Add($h_IL, $h_HBitmap)
		_WinAPI_DeleteObject($h_HBitmap)
	Next
	$s_TD = StringFormat('TimerDiff: %d msec', Round(TimerDiff($i_Timer)))
	$h_HBitmap = 0
	$h_Gui = GUICreate('Example_2', 250, 270)
	GUICtrlCreateLabel($s_TD, 5, 5, 240, 20, BitOR($GUI_SS_DEFAULT_LABEL, $SS_CENTER, $SS_CENTERIMAGE))
	$h_ListView = GUICtrlCreateListView('', 10, 30, 230, 230)
	_GUICtrlListView_SetImageList($h_ListView, $h_IL, 1)
	_GUICtrlListView_AddColumn($h_ListView, 'Country', 200)
	For $i = 0 To UBound($a_Country) - 1
		_GUICtrlListView_AddItem($h_ListView, $a_Country[$i], $i)
	Next
	GUISetState()
	While 1
		Switch GUIGetMsg()
			Case $GUI_EVENT_CLOSE
				ExitLoop
		EndSwitch
	WEnd
	_GUIImageList_Destroy($h_IL)
	GUIDelete()
EndFunc   ;==>_Example_2

Func _Example_1($s_Country)
	Local Const $__STM_SETIMAGE = 0x0172
	Local $h_Gui, $i_Pic, $h_HBitmap, $s_TD
;~ 	---
	Local $i_Timer = TimerInit()
;~ 	---
	$h_HBitmap = _GetCountryFlagHBitmapString($s_Country)
	$s_TD = StringFormat('TimerDiff: %d msec', Round(TimerDiff($i_Timer)))
	$h_Gui = GUICreate('1', 150, 76)
	GUICtrlCreateLabel($s_TD, 5, 5, 140, 20, BitOR($GUI_SS_DEFAULT_LABEL, $SS_CENTER, $SS_CENTERIMAGE))
	$i_Pic = GUICtrlCreatePic('', 67, 45, 16, 11)
	GUICtrlSendMsg($i_Pic, $__STM_SETIMAGE, 0, $h_HBitmap)
	GUISetState()
	While 1
		Switch GUIGetMsg()
			Case $GUI_EVENT_CLOSE
				ExitLoop
		EndSwitch
	WEnd
	_WinAPI_DeleteObject($h_HBitmap)
	GUIDelete()
EndFunc   ;==>_Example_1

Func _GetCountryFlagHBitmapString($s_Country)
	Local Const $i_Width = 16, $i_Height = 11, $s_TableFlags = @ScriptDir & '\flag1.jpg'; можно, ИМХО, $s_TableFlags объявить Global Const
	Local $a_OffSet, $h_Image, $h_Frame, $h_HBitmap, $i_Err = 1

	If StringRegExp($s_Country, '[^A-Z]') Or StringLen($s_Country) <> 2 Then Return SetError(-1, 0, 0)
	$a_OffSet = StringSplit($s_Country, '', 2)
	$a_OffSet[0] = 20 + (Asc($a_OffSet[0]) - 65) * $i_Width
	$a_OffSet[1] = 12 + (Asc($a_OffSet[1]) - 65) * $i_Height
	_GDIPlus_Startup()
	Do
		$h_Image = _GDIPlus_ImageLoadFromFile($s_TableFlags)
		If @error Then ExitLoop
		$h_Frame = _GDIPlus_BitmapCloneArea($h_Image, $a_OffSet[0], $a_OffSet[1], $i_Width, $i_Height, $GDIP_PXF32ARGB)
		If Not $h_Frame Then ExitLoop
		$h_HBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($h_Frame)
		If Not $h_HBitmap Then ExitLoop
		$i_Err = 0
	Until 1
	If ($h_Image) And ($h_Image <> -1) Then _GDIPlus_ImageDispose($h_Image); v3.3.8.1
;~ 	If $h_Image Then _GDIPlus_ImageDispose($h_Image); v3.3.12.0
	If $h_Frame Then _GDIPlus_ImageDispose($h_Frame)
	_GDIPlus_Shutdown()
	If $i_Err Then Return SetError(1, 0, 0)
	Return $h_HBitmap
EndFunc   ;==>_GetCountryFlagHBitmapString
Только картинка плохая.

PS
ИМХО, можно переделать функцию с возможностью передавать массив стран, а не только строку, быстрее будет.

Сделал, работает примерно в 1,5 - 2,5 раза быстрее с массивом:
Код:
#include <StaticConstants.au3>
#include <GUIConstantsEx.au3>
#include <GDIPlus.au3>
#include <GuiListView.au3>
#include <GuiImageList.au3>

Opt('MustDeclareVars', 1)

Global Const $s__TableFlags = @ScriptDir & '\flag1.jpg'
If Not FileExists($s__TableFlags) Then Exit 13

_Example_1('NR')
_Example_2()
_Example_3()

Func _Example_3()
	Local $a_Country[26 ^ 2], $i_Ind, $s_Chr, $h_Gui, $h_IL, $ah_HBitmap, $h_ListView, $s_TD

	For $i = 0 To 25
		$s_Chr = Chr($i + 65)
		For $j = 0 To 25
			$a_Country[$i_Ind] = $s_Chr & Chr($j + 65)
			$i_Ind += 1
		Next
	Next
	$s_Chr = ''
	$i_Ind = 0
	$h_IL = _GUIImageList_Create(16, 11, 5)
;~ 	---
	Local $i_Timer = TimerInit()
;~ 	---
	$ah_HBitmap = _GetCountryFlagHBitmapArray($a_Country)
	If @error Then Return ConsoleWrite('! Error' & @LF)
	For $i = 0 To UBound($ah_HBitmap) - 1
		_GUIImageList_Add($h_IL, $ah_HBitmap[$i])
		_WinAPI_DeleteObject($ah_HBitmap[$i])
	Next
	$ah_HBitmap = 0
	$s_TD = StringFormat('TimerDiff: %d msec', Round(TimerDiff($i_Timer)))
	$h_Gui = GUICreate('Example_3', 250, 270)
	GUICtrlCreateLabel($s_TD, 5, 5, 240, 20, BitOR($GUI_SS_DEFAULT_LABEL, $SS_CENTER, $SS_CENTERIMAGE))
	$h_ListView = GUICtrlCreateListView('', 10, 30, 230, 230)
	_GUICtrlListView_SetImageList($h_ListView, $h_IL, 1)
	_GUICtrlListView_AddColumn($h_ListView, 'Country', 200)
	For $i = 0 To UBound($a_Country) - 1
		_GUICtrlListView_AddItem($h_ListView, $a_Country[$i], $i)
	Next
	$a_Country = 0
	GUISetState()
	While 1
		Switch GUIGetMsg()
			Case $GUI_EVENT_CLOSE
				ExitLoop
		EndSwitch
	WEnd
	_GUIImageList_Destroy($h_IL)
	GUIDelete()
EndFunc   ;==>_Example_3

Func _Example_2()
	Local $a_Country[11] = ['BA', 'MA', 'GB', 'IL', 'FO', 'PY', 'MO', 'NL', 'RU', 'KZ', 'ZZ'], $h_Gui, $h_IL, $ah_HBitmap, $h_ListView, $s_TD

	$h_IL = _GUIImageList_Create(16, 11, 5)
;~ 	---
	Local $i_Timer = TimerInit()
;~ 	---
	$ah_HBitmap = _GetCountryFlagHBitmapArray($a_Country)
	If @error Then Return ConsoleWrite('! Error' & @LF)
	For $i = 0 To UBound($ah_HBitmap) - 1
		_GUIImageList_Add($h_IL, $ah_HBitmap[$i])
		_WinAPI_DeleteObject($ah_HBitmap[$i])
	Next
	$ah_HBitmap = 0
	$s_TD = StringFormat('TimerDiff: %d msec', Round(TimerDiff($i_Timer)))
	$h_Gui = GUICreate('Example_2', 250, 270)
	GUICtrlCreateLabel($s_TD, 5, 5, 240, 20, BitOR($GUI_SS_DEFAULT_LABEL, $SS_CENTER, $SS_CENTERIMAGE))
	$h_ListView = GUICtrlCreateListView('', 10, 30, 230, 230)
	_GUICtrlListView_SetImageList($h_ListView, $h_IL, 1)
	_GUICtrlListView_AddColumn($h_ListView, 'Country', 200)
	For $i = 0 To UBound($a_Country) - 1
		_GUICtrlListView_AddItem($h_ListView, $a_Country[$i], $i)
	Next
	$a_Country = 0
	GUISetState()
	While 1
		Switch GUIGetMsg()
			Case $GUI_EVENT_CLOSE
				ExitLoop
		EndSwitch
	WEnd
	_GUIImageList_Destroy($h_IL)
	GUIDelete()
EndFunc   ;==>_Example_2

Func _Example_1($s_Country)
	Local Const $__STM_SETIMAGE = 0x0172
	Local $h_Gui, $i_Pic, $ah_HBitmap, $s_TD

;~ 	---
	Local $i_Timer = TimerInit()
;~ 	---
	$ah_HBitmap = _GetCountryFlagHBitmapArray($s_Country)
	$s_TD = StringFormat('TimerDiff: %d msec', Round(TimerDiff($i_Timer)))
	$h_Gui = GUICreate('1', 150, 76)
	GUICtrlCreateLabel($s_TD, 5, 5, 140, 20, BitOR($GUI_SS_DEFAULT_LABEL, $SS_CENTER, $SS_CENTERIMAGE))
	$i_Pic = GUICtrlCreatePic('', 67, 45, 16, 11)
	GUICtrlSendMsg($i_Pic, $__STM_SETIMAGE, 0, $ah_HBitmap[0])
	GUISetState()
	While 1
		Switch GUIGetMsg()
			Case $GUI_EVENT_CLOSE
				ExitLoop
		EndSwitch
	WEnd
	_WinAPI_DeleteObject($ah_HBitmap[0])
	GUIDelete()
EndFunc   ;==>_Example_1

Func _GetCountryFlagHBitmapArray($v_Country)
	Local Const $i_Size[2] = [16, 11], $a_StartOffSet[2] = [20, 12]
	Local $i_Ub, $a_Tmp, $h_Image, $h_Frame, $i_Err = 1

	$i_Ub = UBound($v_Country)
	If $i_Ub Then
		Local $a_OffSet[$i_Ub][2]
		Local $ah_HBitmap[$i_Ub]
		For $i = 0 To $i_Ub - 1
			If StringRegExp($v_Country[$i], '[^A-Z]') Or StringLen($v_Country[$i]) <> 2 Then Return SetError(-1, 0, 0)
			$a_Tmp = StringSplit($v_Country[$i], '', 2)
			For $j = 0 To 1
				$a_OffSet[$i][$j] = $a_StartOffSet[$j] + (Asc($a_Tmp[$j]) - 65) * $i_Size[$j]
			Next
		Next
	Else
		If StringRegExp($v_Country, '[^A-Z]') Or StringLen($v_Country) <> 2 Then Return SetError(-1, 0, 0)
		Local $a_OffSet[1][2]
		Local $ah_HBitmap[1]
		$a_Tmp = StringSplit($v_Country, '', 2)
		For $j = 0 To 1
			$a_OffSet[0][$j] = $a_StartOffSet[$j] + (Asc($a_Tmp[$j]) - 65) * $i_Size[$j]
		Next
	EndIf
	_GDIPlus_Startup()
	Do
		$h_Image = _GDIPlus_ImageLoadFromFile($s__TableFlags)
		If @error Then ExitLoop
		For $i = 0 To UBound($ah_HBitmap) - 1
			$h_Frame = _GDIPlus_BitmapCloneArea($h_Image, $a_OffSet[$i][0], $a_OffSet[$i][1], $i_Size[0], $i_Size[1], $GDIP_PXF32ARGB)
			If Not $h_Frame Then ExitLoop 2
			$ah_HBitmap[$i] = _GDIPlus_BitmapCreateHBITMAPFromBitmap($h_Frame)
			_GDIPlus_ImageDispose($h_Frame)
			$h_Frame = 0
			If Not $ah_HBitmap[$i] Then ExitLoop 2
		Next
		$i_Err = 0
	Until 1
	If ($h_Image) And ($h_Image <> -1) Then _GDIPlus_ImageDispose($h_Image); v3.3.8.1
;~ 	If $h_Image Then _GDIPlus_ImageDispose($h_Image); v3.3.12.0
	If $h_Frame Then _GDIPlus_ImageDispose($h_Frame)
	_GDIPlus_Shutdown()
	If $i_Err Then Return SetError(1, 0, 0)
	Return $ah_HBitmap
EndFunc   ;==>_GetCountryFlagHBitmapArray

PPS
А еще добавить возможность выбора картинки-таблицы из ресурсов.
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
madmasles
Спасибо, то что нужно.
Один вопрос, почему _GDIPlus_ImageLoadFromFile запускается в цикле, когда достаточно вызвать один раз?
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
CreatoR [?]
почему _GDIPlus_ImageLoadFromFile запускается в цикле, когда достаточно вызвать один раз?
Так функция один раз и вызывается, или я не правильно понял Ваш вопрос?
 
Автор
CreatoR

CreatoR

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

Вот ещё бы сделать игнорирование пустышек... :whistle:
 
Автор
CreatoR

CreatoR

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

Код:
Func _GDIPlus_GetCountryFlagsFromSheet($sFile, $v_Country)
	If Not FileExists($sFile) Then
		Return SetError(-1, 0, 0)
	EndIf
	
	Local Const $i_Size[2] = [16, 11], $a_StartOffSet[2] = [20, 12]
	Local $a_OffSet[1][2], $ah_HBitmap[1]
	Local $i_Ub, $a_Tmp, $h_Image, $h_Frame
	
	$i_Ub = UBound($v_Country)
	
	If $i_Ub Then
		Dim $a_OffSet[$i_Ub][2]
		Dim $ah_HBitmap[$i_Ub]
		
		For $i = 0 To $i_Ub - 1
			If StringRegExp($v_Country[$i], '[^A-Za-z]') Or StringLen($v_Country[$i]) <> 2 Then
				Return SetError(-2, 0, 0)
			EndIf
			
			$a_Tmp = StringSplit(StringUpper($v_Country[$i]), '', 2)
			
			For $j = 0 To 1
				$a_OffSet[$i][$j] = $a_StartOffSet[$j] + (Asc($a_Tmp[$j]) - 65) * $i_Size[$j]
			Next
		Next
	Else
		If StringRegExp($v_Country, '[^A-Za-z]') Or StringLen($v_Country) <> 2 Then
			Return SetError(-2, 0, 0)
		EndIf
		
		$a_Tmp = StringSplit(StringUpper($v_Country), '', 2)
		
		For $j = 0 To 1
			$a_OffSet[0][$j] = $a_StartOffSet[$j] + (Asc($a_Tmp[$j]) - 65) * $i_Size[$j]
		Next
	EndIf
	
	$h_Image = _GDIPlus_ImageLoadFromFile($sFile)
	
	If @error Then
		Return SetError(1, 0, 0)
	EndIf
	
	For $i = 0 To UBound($ah_HBitmap) - 1
		$h_Frame = _GDIPlus_BitmapCloneArea($h_Image, $a_OffSet[$i][0], $a_OffSet[$i][1], $i_Size[0], $i_Size[1], $GDIP_PXF32ARGB)
		
		If Not $h_Frame Then
			Return SetError(1, 0, 0)
		EndIf
		
		$ah_HBitmap[$i] = _GDIPlus_BitmapCreateHBITMAPFromBitmap($h_Frame)
		_GDIPlus_ImageDispose($h_Frame)
		
		If Not $ah_HBitmap[$i] Then
			Return SetError(1, 0, 0)
		EndIf
	Next
	
	If $h_Image And $h_Image <> -1 Then
		_GDIPlus_ImageDispose($h_Image)
	EndIf
	
	Return $ah_HBitmap
EndFunc
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
CreatoR [?]
чтобы работала с любым регистром букв
У меня это было, но потом убрал для скорости.

Функция эта будет работать только с приложенным файлом, так что, ИМХО, нет смысла задавать файл в качестве аргумента.

[?]
Вот ещё бы сделать игнорирование пустышек
Я могу переделать файл-таблицу (у меня есть 236 картинок-флагов размером 16х13) и сделать замену на ZZ, если нет картинки флага.

CreatoR [?]
Тогда зачем цикл, для установки кода ошибки?
Мне так удобнее, привык уже к такой конструкции. :smile:

madmasles [?]
добавить возможность выбора картинки-таблицы из ресурсов.
Сделал, но из ресурсов у меня работает только с *.png, так что надо сначала переконвертировать скриптом flag1.jpg в flag1.png:
Код:
;~ AutoIt Version: 3.3.8.1+

#include <GDIPlus.au3>

Global $hImage, $hHBitmap, $aSize, $tBits, $hBitmap, $iErr = 1

If FileExists(@ScriptDir & '\flag1.png') Then FileDelete(@ScriptDir & '\flag1.png')
_GDIPlus_Startup()
Do
	$hImage = _GDIPlus_ImageLoadFromFile(@ScriptDir & '\flag1.jpg')
	If @error Then ExitLoop
	$aSize = _GDIPlus_ImageGetDimension__($hImage)
	If @error Then ExitLoop
	$hHBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage)
	If @error Then ExitLoop
	_GDIPlus_ImageDispose($hImage)
	$hImage = 0
	$tBits = DllStructCreate('dword[' & $aSize[0] * $aSize[1] & ']')
	_WinAPI_GetBitmapBits__($hHBitmap, DllStructGetSize($tBits), $tBits)
	If @error Then ExitLoop
	_WinAPI_DeleteObject($hHBitmap)
	$hHBitmap = 0
	$hBitmap = _GDIPlus_BitmapCreateFromScan0__($aSize[0], $aSize[1], 4 * $aSize[0], $GDIP_PXF32ARGB, $tBits)
	If @error Then ExitLoop
	_GDIPlus_ImageSaveToFile($hBitmap, @ScriptDir & '\flag1.png')
	If @error Then ExitLoop
	_GDIPlus_ImageDispose($hBitmap)
	$hBitmap = 0
	$iErr = 0
Until 1
If $iErr Then
	If $hImage Then _GDIPlus_ImageDispose($hImage)
	If $hBitmap Then _GDIPlus_ImageDispose($hBitmap)
	If $hHBitmap Then _WinAPI_DeleteObject($hHBitmap)
	ConsoleWrite('Error' & @LF)
Else
	ConsoleWrite('OK' & @LF)
EndIf
_GDIPlus_Shutdown()


Func _GDIPlus_BitmapCreateFromScan0__($iWidth, $iHeight, $iStride = 0, $iPixelFormat = 0x0026200A, $tScan0 = 0)
	Local $aResult = DllCall('gdiplus.dll', 'uint', 'GdipCreateBitmapFromScan0', 'int', $iWidth, 'int', $iHeight, 'int', $iStride, _
			'int', $iPixelFormat, 'struct*', $tScan0, 'handle*', 0)

	If (@error) Or ($aResult[0]) Then Return SetError(1, 0, 0)
	Return $aResult[6]
EndFunc   ;==>_GDIPlus_BitmapCreateFromScan0__

Func _GDIPlus_ImageGetDimension__($hImage)
	Local $aSize[2], $aResult

	$aResult = DllCall('gdiplus.dll', 'uint', 'GdipGetImageDimension', 'hwnd', $hImage, 'float*', 0, 'float*', 0)
	If (@error) Or ($aResult[0]) Then Return SetError(1, 0, 0)
	$aSize[0] = $aResult[2]
	$aSize[1] = $aResult[3]
	Return $aSize
EndFunc   ;==>_GDIPlus_ImageGetDimension__

Func _WinAPI_GetBitmapBits__($hBitmap, $iSize, $tBits)
	Local $Ret = DllCall('gdi32.dll', 'dword', 'GetBitmapBits', 'ptr', $hBitmap, 'dword', $iSize, 'struct*', $tBits)

	If (@error) Or (Not $Ret[0]) Then Return SetError(1, 0, 0)
	Return $Ret[0]
EndFunc   ;==>_WinAPI_GetBitmapBits__
А уже потом:
Код:
#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Compression=4
#AutoIt3Wrapper_Res_File_Add=flag1.png, PNG, 200
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****

;~ AutoIt Version: 3.3.8.1+

#include <StaticConstants.au3>
#include <GUIConstantsEx.au3>
#include <GDIPlus.au3>
#include <GuiListView.au3>
#include <GuiImageList.au3>

Opt('MustDeclareVars', 1)

Global Const $a__TableFlags[2][2] = [[@ScriptDir & '\flag1.png'],['PNG', 200]]
If Not @Compiled Then
	If Not FileExists($a__TableFlags[0][0]) Then Exit 13
EndIf
_Example_1('NR')
_Example_2()
_Example_3()

Func _Example_3()
	Local $a_Country[26 ^ 2], $i_Ind, $s_Chr, $h_Gui, $h_IL, $ah_HBitmap, $h_ListView, $s_TD

	For $i = 0 To 25
		$s_Chr = Chr($i + 65)
		For $j = 0 To 25
			$a_Country[$i_Ind] = $s_Chr & Chr($j + 65)
			$i_Ind += 1
		Next
	Next
	$s_Chr = ''
	$i_Ind = 0
	$h_IL = _GUIImageList_Create(16, 11, 5)
;~ 	---
	Local $i_Timer = TimerInit()
;~ 	---
	$ah_HBitmap = _GetCountryFlagHBitmapArrayEx($a_Country)
	If @error Then
		If @Compiled Then
			Return MsgBox(16, 'Error', 'Error _Example_3 _GetCountryFlagHBitmapArrayEx')
		Else
			Return ConsoleWrite('! Error' & @LF)
		EndIf
	EndIf
	For $i = 0 To UBound($ah_HBitmap) - 1
		_GUIImageList_Add($h_IL, $ah_HBitmap[$i])
		_WinAPI_DeleteObject($ah_HBitmap[$i])
	Next
	$ah_HBitmap = 0
	$s_TD = StringFormat('TimerDiff: %d msec', Round(TimerDiff($i_Timer)))
	$h_Gui = GUICreate('Example_3', 250, 270)
	GUICtrlCreateLabel($s_TD, 5, 5, 240, 20, BitOR($GUI_SS_DEFAULT_LABEL, $SS_CENTER, $SS_CENTERIMAGE))
	$h_ListView = GUICtrlCreateListView('', 10, 30, 230, 230)
	_GUICtrlListView_SetImageList($h_ListView, $h_IL, 1)
	_GUICtrlListView_AddColumn($h_ListView, 'Country', 200)
	For $i = 0 To UBound($a_Country) - 1
		_GUICtrlListView_AddItem($h_ListView, $a_Country[$i], $i)
	Next
	$a_Country = 0
	GUISetState()
	While 1
		Switch GUIGetMsg()
			Case $GUI_EVENT_CLOSE
				ExitLoop
		EndSwitch
	WEnd
	_GUIImageList_Destroy($h_IL)
	GUIDelete()
EndFunc   ;==>_Example_3

Func _Example_2()
	Local $a_Country[11] = ['BA', 'MA', 'GB', 'IL', 'FO', 'PY', 'MO', 'NL', 'RU', 'KZ', 'ZZ'], $h_Gui, $h_IL, $ah_HBitmap, $h_ListView, $s_TD

	$h_IL = _GUIImageList_Create(16, 11, 5)
;~ 	---
	Local $i_Timer = TimerInit()
;~ 	---
	$ah_HBitmap = _GetCountryFlagHBitmapArrayEx($a_Country)
	If @error Then
		If @Compiled Then
			Return MsgBox(16, 'Error', 'Error _Example_2 _GetCountryFlagHBitmapArrayEx')
		Else
			Return ConsoleWrite('! Error' & @LF)
		EndIf
	EndIf
	For $i = 0 To UBound($ah_HBitmap) - 1
		_GUIImageList_Add($h_IL, $ah_HBitmap[$i])
		_WinAPI_DeleteObject($ah_HBitmap[$i])
	Next
	$ah_HBitmap = 0
	$s_TD = StringFormat('TimerDiff: %d msec', Round(TimerDiff($i_Timer)))
	$h_Gui = GUICreate('Example_2', 250, 270)
	GUICtrlCreateLabel($s_TD, 5, 5, 240, 20, BitOR($GUI_SS_DEFAULT_LABEL, $SS_CENTER, $SS_CENTERIMAGE))
	$h_ListView = GUICtrlCreateListView('', 10, 30, 230, 230)
	_GUICtrlListView_SetImageList($h_ListView, $h_IL, 1)
	_GUICtrlListView_AddColumn($h_ListView, 'Country', 200)
	For $i = 0 To UBound($a_Country) - 1
		_GUICtrlListView_AddItem($h_ListView, $a_Country[$i], $i)
	Next
	$a_Country = 0
	GUISetState()
	While 1
		Switch GUIGetMsg()
			Case $GUI_EVENT_CLOSE
				ExitLoop
		EndSwitch
	WEnd
	_GUIImageList_Destroy($h_IL)
	GUIDelete()
EndFunc   ;==>_Example_2

Func _Example_1($s_Country)
	Local Const $__STM_SETIMAGE = 0x0172
	Local $h_Gui, $i_Pic, $ah_HBitmap, $s_TD

;~ 	---
	Local $i_Timer = TimerInit()
;~ 	---
	$ah_HBitmap = _GetCountryFlagHBitmapArrayEx($s_Country)
	If @error Then
		If @Compiled Then
			Return MsgBox(16, 'Error', 'Error _Example_1 _GetCountryFlagHBitmapArrayEx')
		Else
			Return ConsoleWrite('! Error' & @LF)
		EndIf
	EndIf
	$s_TD = StringFormat('TimerDiff: %d msec', Round(TimerDiff($i_Timer)))
	$h_Gui = GUICreate('1', 150, 76)
	GUICtrlCreateLabel($s_TD, 5, 5, 140, 20, BitOR($GUI_SS_DEFAULT_LABEL, $SS_CENTER, $SS_CENTERIMAGE))
	$i_Pic = GUICtrlCreatePic('', 67, 45, 16, 11)
	GUICtrlSendMsg($i_Pic, $__STM_SETIMAGE, 0, $ah_HBitmap[0])
	GUISetState()
	While 1
		Switch GUIGetMsg()
			Case $GUI_EVENT_CLOSE
				ExitLoop
		EndSwitch
	WEnd
	_WinAPI_DeleteObject($ah_HBitmap[0])
	GUIDelete()
EndFunc   ;==>_Example_1

Func _GetCountryFlagHBitmapArrayEx($v_Country)
	Local Const $ai_Size[2] = [16, 11], $a_StartOffSet[2] = [20, 12]
	Local $i_Ub, $a_Tmp, $h_Image, $h_Frame, $i_Err = 1

	$i_Ub = UBound($v_Country)
	If $i_Ub Then
		Local $a_OffSet[$i_Ub][2]
		Local $ah_HBitmap[$i_Ub]
		For $i = 0 To $i_Ub - 1
			If StringRegExp($v_Country[$i], '[^A-Z]') Or StringLen($v_Country[$i]) <> 2 Then Return SetError(-1, 0, 0)
			$a_Tmp = StringSplit($v_Country[$i], '', 2)
			For $j = 0 To 1
				$a_OffSet[$i][$j] = $a_StartOffSet[$j] + (Asc($a_Tmp[$j]) - 65) * $ai_Size[$j]
			Next
		Next
	Else
		If StringRegExp($v_Country, '[^A-Z]') Or StringLen($v_Country) <> 2 Then Return SetError(-1, 0, 0)
		Local $a_OffSet[1][2]
		Local $ah_HBitmap[1]
		$a_Tmp = StringSplit($v_Country, '', 2)
		For $j = 0 To 1
			$a_OffSet[0][$j] = $a_StartOffSet[$j] + (Asc($a_Tmp[$j]) - 65) * $ai_Size[$j]
		Next
	EndIf
	_GDIPlus_Startup()
	Do
		$h_Image = __Load_Image()
		If @error Then ExitLoop
		For $i = 0 To UBound($ah_HBitmap) - 1
			$h_Frame = _GDIPlus_BitmapCloneArea($h_Image, $a_OffSet[$i][0], $a_OffSet[$i][1], $ai_Size[0], $ai_Size[1], $GDIP_PXF32ARGB)
			If Not $h_Frame Then ExitLoop 2
			$ah_HBitmap[$i] = _GDIPlus_BitmapCreateHBITMAPFromBitmap($h_Frame)
			_GDIPlus_ImageDispose($h_Frame)
			$h_Frame = 0
			If Not $ah_HBitmap[$i] Then ExitLoop 2
		Next
		$i_Err = 0
	Until 1
	If ($h_Image) And ($h_Image <> -1) Then _GDIPlus_ImageDispose($h_Image)
	If $h_Frame Then _GDIPlus_ImageDispose($h_Frame)
	_GDIPlus_Shutdown()
	If $i_Err Then Return SetError(1, 0, 0)
	Return $ah_HBitmap
EndFunc   ;==>_GetCountryFlagHBitmapArrayEx

Func __Load_Image()
	Local $h_Image, $a_Res

	If @Compiled Then
		Do
			Local $i_Err = 1, $h_SelfModule, $h_Inf, $h_Res, $ai_Size, $p_Res, $h_Mem, $p_Mem, $h_Stream, $h_Image

			$a_Res = DllCall('kernel32.dll', 'handle', 'GetModuleHandleW', 'ptr', 0)
			If (@error) Or (Not $a_Res[0]) Then ExitLoop
			$h_SelfModule = $a_Res[0]
			$a_Res = DllCall('kernel32.dll', 'ptr', 'FindResourceW', 'handle', $h_SelfModule, 'int', $a__TableFlags[@Compiled][1], 'wstr', $a__TableFlags[@Compiled][0])
			If (@error) Or (Not $a_Res[0]) Then ExitLoop
			$h_Inf = $a_Res[0]
			$a_Res = DllCall('kernel32.dll', 'ptr', 'LoadResource', 'handle', $h_SelfModule, 'ptr', $h_Inf)
			If (@error) Or (Not $a_Res[0]) Then ExitLoop
			$h_Res = $a_Res[0]
			$a_Res = DllCall('kernel32.dll', 'dword', 'SizeofResource', 'handle', $h_SelfModule, 'ptr', $h_Inf)
			If (@error) Or (Not $a_Res[0]) Then ExitLoop
			$ai_Size = $a_Res[0]
			$a_Res = DllCall('kernel32.dll', 'ptr', 'LockResource', 'ptr', $h_Res)
			If (@error) Or (Not $a_Res[0]) Then ExitLoop
			$p_Res = $a_Res[0]
			$a_Res = DllCall('kernel32.dll', 'handle', 'GlobalAlloc', 'uint', 0x0002, 'ulong_ptr', $ai_Size);$GMEM_MOVEABLE = 0x0002
			If (@error) Or (Not $a_Res[0]) Then ExitLoop
			$h_Mem = $a_Res[0]
			$a_Res = DllCall('kernel32.dll', 'ptr', 'GlobalLock', 'ptr', $h_Mem)
			If (@error) Or (Not $a_Res[0]) Then ExitLoop
			$p_Mem = $a_Res[0]
			DllCall('kernel32.dll', 'none', 'RtlMoveMemory', 'ptr', $p_Mem, 'ptr', $p_Res, 'ulong_ptr', $ai_Size)
			If @error Then ExitLoop
			$a_Res = DllCall('kernel32.dll', 'int', 'GlobalUnlock', 'ptr', $h_Mem)
			If (@error) Or ($a_Res[0]) Then ExitLoop
			$a_Res = DllCall('ole32.dll', 'uint', 'CreateStreamOnHGlobal', 'ptr', $h_Mem, 'int', 1, 'ptr*', 0)
			If (@error) Or ($a_Res[0]) Then ExitLoop
			$h_Stream = $a_Res[3]
			$a_Res = DllCall('gdiplus.dll', 'uint', 'GdipCreateBitmapFromStream', 'ptr', $h_Stream, 'ptr*', 0)
			If (@error) Or ($a_Res[0]) Or (Not $a_Res[2]) Then ExitLoop
			$h_Image = $a_Res[2]
			$a_Res = DllCall('oleaut32.dll', 'uint', 'DispCallFunc', 'ptr', $h_Stream, 'uint', 8 * (1 + @AutoItX64), 'uint', 4, _
					'uint', 23, 'uint', 0, 'ptr', 0, 'ptr', 0, 'str', '')
			If (@error) Or ($a_Res[0]) Then ExitLoop
			$h_Stream = 0
			$a_Res = DllCall('kernel32.dll', 'ptr', 'GlobalFree', 'ptr', $h_Mem)
			If (@error) Or ($a_Res[0]) Then ExitLoop
			$h_Mem = 0
			$i_Err = 0
		Until 1
		If $i_Err Then
			If $h_Stream Then DllCall('oleaut32.dll', 'uint', 'DispCallFunc', 'ptr', $h_Stream, 'uint', 8 * (1 + @AutoItX64), 'uint', 4, _
					'uint', 23, 'uint', 0, 'ptr', 0, 'ptr', 0, 'str', '')
			If $h_Mem Then DllCall('kernel32.dll', 'ptr', 'GlobalFree', 'ptr', $h_Mem)
			If ($h_Image) And ($h_Image <> -1) Then _GDIPlus_ImageDispose($h_Image)
			Return SetError(1, 0, 0)
		EndIf
	Else
		$h_Image = _GDIPlus_ImageLoadFromFile($a__TableFlags[@Compiled][0])
		If @error Then Return SetError(1, 0, 0)
	EndIf
	Return $h_Image
EndFunc   ;==>__Load_Image
 
Автор
CreatoR

CreatoR

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

Я могу переделать файл-таблицу (у меня есть 236 картинок-флагов размером 16х13) и сделать замену на ZZ, если нет картинки флага.
Было бы круто :smile:.

Вот тут есть иконки в неплохом качестве.
 
Верх