Что нового

Многоуровневая структура DLL

musicstashall

Знающий
Сообщения
322
Репутация
7
Версия AutoIt: 3.

Описание:
Может быть я даже неправильно формулирую вопрос, но я столкнулся с задачей создать структуру, в которой имеются подструктуры, не хватает ума разобраться, прошу помощи. Ниже представлен код C, по аналогии которого и необходимо создать структуру:

Код:
struct ACCENTPOLICY
{
	int nAccentState;
	int nFlags;
	int nColor;
	int nAnimationId;
};
struct WINCOMPATTRDATA
{
	int nAttribute;
	PVOID pData;
	ULONG ulDataSize;
};

struct OPTIONS
{
	int Appearance;
	int Color;
} opt;

Дальше задаются значения в структуру, выглядит это так:

Код:
	{
		ACCENTPOLICY policy;

		policy = { opt.Appearance, 2, opt.Color, 0 };

		WINCOMPATTRDATA data = { 19, &policy, sizeof(ACCENTPOLICY) }; // WCA_ACCENT_POLICY=19
	}

Я создал только ACCENTPOLICY и WINCOMPATTRDATA, а вот с OPTIONS я не понял, как следует поступить, здесь как раз имеем дело с подструктурой:

Код:
Global $ACCENT_POLICY = DllStructCreate('int AccentState; int AccentFlags; int GradientColor; int AnimationId')
Global $ATTRIB_DATA = DllStructCreate('dword Attribute; ptr DataBuffer; ulong Size')
Global $OPTIONS = DllStructCreate('int Appearance; int Color')

$ATTRIB_DATA.Attribute = 19
$ATTRIB_DATA.DataBuffer = ; policy = { opt.Appearance, 2, opt.Color, 0 }
$ATTRIB_DATA.Size = DllStructGetSize($ACCENT_POLICY)


Не понятно, как сформировать такую строку:

Код:
policy = { opt.Appearance, 2, opt.Color, 0 };

Плиз, прошу помощи.
 

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
Код:
Global Const $tagACCENTPOLICY = 'int AccentState; int AccentFlags; int GradientColor; int AnimationId'
Global Const $tagWINCOMPATTRDATA = 'int nAttribute; ptr pData; ulong ulDataSize;'
Global Const $tagOPTIONS = 'int Appearance; int Color;'
Global Const $WCA_ACCENT_POLICY = 19
;~ ACCENTPOLICY policy;
Local $tPolicy = DllStructCreate($tagACCENTPOLICY)

;Кусок кода не приведен, поэтому на вскидку так.
Local $tOptions = DllStructCreate($tagOPTIONS, Нужен указатель если вы работаете со структурой не вами созданной)

;~ policy = { opt.Appearance, 2, opt.Color, 0 };
DllStructSetData($tPolicy, 'AccentState', DllStructGetData($tOptions, 'Appearance'))
DllStructSetData($tPolicy, 'AccentFlags', 2)
DllStructSetData($tPolicy, 'GradientColor', DllStructGetData($tOptions, 'Color'))
DllStructSetData($tPolicy, 'AnimationId', 0)

;~ WINCOMPATTRDATA data = { 19, &policy, sizeof(ACCENTPOLICY) }; // WCA_ACCENT_POLICY=19
Local $tWinCompattrData = DllStructCreate($tagWINCOMPATTRDATA, Нужен указатель если вы работаете со структурой не вами созданной)

DllStructSetData($tWinCompattrData, 'nAttribute', $WCA_ACCENT_POLICY)
DllStructSetData($tWinCompattrData, 'pData', DllStructGetPtr($tPolicy))
DllStructSetData($tWinCompattrData, 'ulDataSize', DllStructGetSize($tPolicy))
 
Автор
M

musicstashall

Знающий
Сообщения
322
Репутация
7
Весь исходник на C:

Код:
#include <windows.h>
#include <iostream>
#include <string>

//used for the tray things
#include <shellapi.h>
#include "resource.h"

bool run = true; //needed for tray exit

#pragma region composition

struct ACCENTPOLICY
{
	int nAccentState;
	int nFlags;
	int nColor;
	int nAnimationId;
};
struct WINCOMPATTRDATA
{
	int nAttribute;
	PVOID pData;
	ULONG ulDataSize;
};

struct OPTIONS
{
	int taskbar_appearance;
	int color;
} opt;

const int ACCENT_ENABLE_GRADIENT = 1; // Makes the taskbar a solid color specified by nColor. This mode doesn't care about the alpha channel.
const int ACCENT_ENABLE_TRANSPARENTGRADIENT = 2; // Makes the taskbar a tinted transparent overlay. nColor is the tint color, sending nothing results in it interpreted as 0x00000000 (totally transparent, blends in with desktop)
const int ACCENT_ENABLE_BLURBEHIND = 3; // Makes the taskbar a tinted blurry overlay. nColor is same as above.



typedef BOOL(WINAPI*pSetWindowCompositionAttribute)(HWND, WINCOMPATTRDATA*);
static pSetWindowCompositionAttribute SetWindowCompositionAttribute = (pSetWindowCompositionAttribute)GetProcAddress(GetModuleHandle(TEXT("user32.dll")), "SetWindowCompositionAttribute");

void SetWindowBlur(HWND hWnd)
{
	if (SetWindowCompositionAttribute)
	{
		ACCENTPOLICY policy;

		policy = { opt.taskbar_appearance, 2, opt.color, 0 };

		WINCOMPATTRDATA data = { 19, &policy, sizeof(ACCENTPOLICY) }; // WCA_ACCENT_POLICY=19
		SetWindowCompositionAttribute(hWnd, &data);
	}

}

#pragma endregion 


#pragma region command line
void PrintHelp()
{
	// BUG - 
	// For some reason, when launching this program in cmd.exe, it won't properly "notice"
	// when the program has exited, and will not automatically write a new prompt to the console.
	// Instead of printing the current directory as usual before it waits for a new command,
	// it doesn't print anything, leading to a cluttered console.
	// It's even worse in Powershell, where it actually WILL print the PS prompt before waiting for 
	// a new command, but it does so on the line after "./TranslucentTB.exe --help", overwriting the 
	// first line of output from this function, and gradually overwriting the following lines as you
	// press enter. The PS shell just doesn't notice that anything gets printed to the console, and
	// therefore it prints the PS prompt over this output instead of after. I don't know of any 
	// solution to this, but I expect that setting the project type to SUBSYSTEM:CONSOLE would solve
	// those issues. Again - I think a help file would be the best solution, so I'll do that in my 
	// next commit.

	BOOL hasconsole = true;
	BOOL createdconsole = false;
	// Try to attach to the parent console,
	// allocate a new one if that isn't successful
	if (!AttachConsole(ATTACH_PARENT_PROCESS))
	{
		if (!AllocConsole())
		{
			hasconsole = false;
		}
		else
		{
			createdconsole = true;
		}
	}

	if (hasconsole)
	{
		FILE* outstream;
		FILE* instream;
		freopen_s(&outstream, "CONOUT$", "w", stdout);
		freopen_s(&instream, "CONIN$", "w", stdin);

		if (outstream)
		{
			using namespace std;
			cout << endl;
			cout << "TranslucentTB by /u/IronManMark20" << endl;
			cout << "This program modifies the apperance of the windows taskbar" << endl;
			cout << "You can modify its behaviour by using the following parameters when launching the program:" << endl;
			cout << "  --blur        | will make the taskbar a blurry overlay of the background (default)." << endl;
			cout << "  --opaque      | will make the taskbar a solid color specified by the tint parameter." << endl;
			cout << "  --transparent | will make the taskbar a transparent color specified by the tint parameter. " << endl;
			cout << "                  the value of the alpha channel determines the opacity of the taskbar." << endl;
			cout << "  --tint COLOR  | specifies the color applied to the taskbar. COLOR is 32 bit number in hex format," << endl;
			cout << "                  see explanation below. This will not affect the blur mode. If COLOR is zero in" << endl;
			cout << "                  combination with --transparent the taskbar becomes opaque and uses the selected" << endl;
			cout << "                  system color scheme." << endl;
			cout << "  --help        | Displays this help message." << endl;
			cout << endl;

			cout << "Color format:" << endl;
			cout << "  The parameter is interpreted as a three or four byte long number in hexadecimal format that" << endl;
			cout << "  describes the four color channels ([alpha,] red, green and blue). These look like this:" << endl;
			cout << "  0x80fe10a4 (the '0x' is optional). You often find colors in this format in the context of HTML and" << endl;
			cout << "  web design, and there are many online tools to convert from familiar names to this format. These" << endl;
			cout << "  tools might give you numbers starting with '#', in that case you can just remove the leading '#'." << endl;
			cout << "  You should be able to find online tools by searching for \"color to hex\" or something similar." << endl;
			cout << "  If the converter doesn't include alpha values (opacity), you can append them yourself at the start" << endl;
			cout << "  of the number. Just convert a value between 0 and 255 to its hexadecimal value before you append it." << endl;
			cout << endl;

			if (createdconsole && instream)
			{	
				string wait;
				
				cout << "Press enter to exit the program." << endl;
				if (!getline(cin, wait))
				{
					// Couldn't wait for user input, make the user close
					// the program themselves so they can see the output.
					cout << "Press Ctrl + C, Alt + F4, or click the close button to exit the program." << endl;
					Sleep(INFINITE);
				}

				FreeConsole();
			}

			fclose(outstream);
		}
	}
}

void ParseOptions()
{
	// Set default value
	opt.taskbar_appearance = ACCENT_ENABLE_BLURBEHIND;

	// Loop through command line arguments
	LPWSTR *szArglist;
	int nArgs;

	szArglist = CommandLineToArgvW(GetCommandLineW(), &nArgs);

	for (int i = 0; i < nArgs; i++)
	{
		LPWSTR arg = szArglist[i];

		if (wcscmp(arg, L"--help") == 0)
		{
			PrintHelp();
			exit(0);
		}
		else if (wcscmp(arg, L"--blur") == 0)
		{
			opt.taskbar_appearance = ACCENT_ENABLE_BLURBEHIND;
		}
		else if (wcscmp(arg, L"--opaque") == 0)
		{
			opt.taskbar_appearance = ACCENT_ENABLE_GRADIENT;
		}
		else if (wcscmp(arg, L"--transparent") == 0)
		{
			opt.taskbar_appearance = ACCENT_ENABLE_TRANSPARENTGRADIENT;
		}
		else if (wcscmp(arg, L"--tint") == 0)
		{
			// The next argument should be a color in hex format
			if (i + 1 < nArgs && wcslen(szArglist[i + 1]) > 0)
			{
				LPWSTR param = szArglist[i + 1];
				unsigned long colval = 0;
				WCHAR* stopchar;


				colval = wcstoul(param, &stopchar, 16);


				// ACCENTPOLICY.nColor expects the byte order to be ABGR,
				// fiddle some bits to make it intuitive for the user.
				opt.color =
					(colval & 0xFF000000) +
					((colval & 0x00FF0000) >> 16) +
					(colval & 0x0000FF00) +
					((colval & 0x000000FF) << 16);
			}
			else
			{
				// TODO error handling for missing value
				// Really not much to do as we don't have functional
				// output streams, and opening a window seems overkill.
			}
		}
	}

	LocalFree(szArglist);
}

#pragma endregion

#pragma region tray

#define WM_NOTIFY_TB 3141

HMENU menu;

LRESULT CALLBACK TBPROCWND(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{

	switch (message)
	{
	case WM_CLOSE:
		PostQuitMessage(0);
		break;
	case WM_NOTIFY_TB:
		if (lParam == WM_LBUTTONUP)
		{
			POINT pt;
			GetCursorPos(&pt);
			SetForegroundWindow(hWnd);
			UINT tray = TrackPopupMenu(menu, TPM_RETURNCMD | TPM_RIGHTALIGN | TPM_NONOTIFY, pt.x, pt.y, 0, hWnd, NULL);
			switch (tray)
			{
			case IDM_BLUR:
				opt.taskbar_appearance = ACCENT_ENABLE_BLURBEHIND;
				break;
			case IDM_CLEAR:
				opt.taskbar_appearance = ACCENT_ENABLE_TRANSPARENTGRADIENT;
				opt.color = 0x000000;
				break;
			case IDM_EXIT:
				run = false;
				break;
			}
		}
	}
	return DefWindowProc(hWnd, message, wParam, lParam);
}

NOTIFYICONDATA Tray;

void initTray(HWND parent)
{

	Tray.cbSize = sizeof(Tray);
	Tray.hIcon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(MAINICON));
	Tray.hWnd = parent;
	wcscpy_s(Tray.szTip, L"TransparentTB");
	Tray.uCallbackMessage = WM_NOTIFY_TB;
	Tray.uFlags = NIF_ICON | NIF_TIP | NIF_MESSAGE;
	Tray.uID = 101;
	Shell_NotifyIcon(NIM_ADD, &Tray);
	Shell_NotifyIcon(NIM_SETVERSION, &Tray);
}

#pragma endregion

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPreInst, LPSTR pCmdLine, int nCmdShow)
{
	MSG msg; // for message translation and dispatch
	HMENU popup = LoadMenu(hInstance, MAKEINTRESOURCE(IDR_POPUP_MENU));
	menu = GetSubMenu(popup, 0);
	WNDCLASSEX wnd = { 0 };

	wnd.hInstance = hInstance;
	wnd.lpszClassName = L"TranslucentTB";
	wnd.lpfnWndProc = TBPROCWND;
	wnd.style = CS_HREDRAW | CS_VREDRAW;
	wnd.cbSize = sizeof(WNDCLASSEX);

	wnd.hIcon = LoadIcon(NULL, IDI_APPLICATION);
	wnd.hCursor = LoadCursor(NULL, IDC_ARROW);
	wnd.hbrBackground = (HBRUSH)BLACK_BRUSH;
	RegisterClassEx(&wnd);

	HWND tray_hwnd = CreateWindowEx(WS_EX_TOOLWINDOW, L"TranslucentTB", L"TrayWindow", WS_OVERLAPPEDWINDOW, 0, 0,
		400, 400, NULL, NULL, hInstance, NULL);

	initTray(tray_hwnd);
  
	ShowWindow(tray_hwnd, WM_SHOWWINDOW);
	ParseOptions(); //command line argument settings
	HWND taskbar = FindWindowW(L"Shell_TrayWnd", NULL);
	HWND secondtaskbar = FindWindow(L"Shell_SecondaryTrayWnd", NULL); // we use this for the taskbars on other monitors.
	while (run) {
		SetWindowBlur(taskbar);
		if (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) {
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
		while (secondtaskbar = FindWindowEx(0, secondtaskbar, L"Shell_SecondaryTrayWnd", L""))
		{
			SetWindowBlur(secondtaskbar);
		}
		Sleep(10);
	}
	Shell_NotifyIcon(NIM_DELETE, &Tray);
}
 

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
Похоже опции это просто хранилище, можете их вообще выкинуть и вписывать просто переменными, например вместо 'GradientColor', DllStructGetData($tOptions, 'Color'), вписывайте 'GradientColor', $iGradientColor
а саму $iGradientColor делайте глобальной, и где нибудь в вашем скрипте, присваивайте ей нужное значение.
 
Автор
M

musicstashall

Знающий
Сообщения
322
Репутация
7
На будущее хотелось бы создать библиотеку _SetWindowCompositionAttribute() и _GetWindowCompositionAttribute(), поэтому давайте напишем сейчас ее)) :IL_AutoIt_1:
 

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
Вот еще тему посмотрите https://www.autoitscript.com/forum/topic/183488-_winapi_dwmenableblurbehindwindow-in-windows-10/
 
Автор
M

musicstashall

Знающий
Сообщения
322
Репутация
7
Код:
DllCall("user32.dll", "bool", "SetWindowCompositionAttribute", "hwnd", $hWnd, "ptr", DllStructGetPtr($tagWINCOMPATTRDATA))



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

DWM всё изучил, не это требуется. По крайней мере мне сейчас нужно задать цвет и прозрачность для панели задач.
 

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
Ну удачи, что еще пожелать :smile: Программка вроде простая, она находит hwnd трея, который Shell_TrayWnd или Shell_SecondaryTrayWnd, и вызывает функцию
SetWindowBlur, которая в свою очередь вызывает WINAPI SetWindowCompositionAttribute из библиотеки user32.dll, похоже эта функция не документирована.
И повторяет это все в цикле.
 
Автор
M

musicstashall

Знающий
Сообщения
322
Репутация
7
Разобрался, сделал, всё работает как надо. Но обнаружил, что при устанорвке атрибутов на какое-либо окно, рисуется так же и подложка под новые бордюры, размеры которых устанавливаются по умолчанию. А если используется тема оформления, в которой бордюры заужены или вообще отсутствуют, то получается естественно некрасиво:


Оказывается, в функции имеется так же еще один подуровень структуры, где как раз и задаются атрибуты для бордюров. Пример на C++:


Код:
_ACCENT_FLAGS {
    DrawLeftBorder = 0x20,
    DrawTopBorder = 0x40,
    DrawRightBorder = 0x80,
    DrawBottomBorder = 0x100,
    DrawAllBorders = (DrawLeftBorder | DrawTopBorder | DrawRightBorder | DrawBottomBorder)
}

Далее, если уже пошло такое дело, то так же необходимо и получить эти атрибуты от текущего окна, чтобы и новые атрибуты задавать соотетственные. Пытался делать что-то такое:

Код:
Func _GetWindowCompositionAttribute($hWnd)
	$tPolicy= DllStructCreate($tagACCENTPOLICY)
	$tOptions = DllStructCreate($tagOPTIONS)
	$tWinCompattrData = DllStructCreate($tagWINCOMPATTRDATA)
	DllStructSetData($tWinCompattrData, 'pData', DllStructGetPtr($tPolicy))
	DllStructSetData($tWinCompattrData, 'ulDataSize', DllStructGetSize($tPolicy))
	DllStructSetData($tPolicy, 'AccentState', DllStructGetData($tOptions, 'Appearance'))
	DllStructSetData($tPolicy, 'AccentFlags', 2)
	DllStructSetData($tPolicy, 'GradientColor', DllStructGetData($tOptions, 'Color'))
	DllStructSetData($tPolicy, 'AnimationId', 0)
	DllCall("user32.dll", "bool", "GetWindowCompositionAttribute", "hwnd", $hWnd, "ptr", $tWinCompattrData)
	
	If @error Then Return SetError(@error, @extended, 0)
	Return $tWinCompattrData
EndFunc


Но в результате, единственное, что получал, это значение pData, причем оно всегда разное от одного и того же окна. Пошу помощи создать структуру _ACCENT_FLAGS:

Код:
Global Const $tagFLAGS = 'int DrawLeftBorder; int DrawTopBorder; int DrawRightBorder; int DrawBottomBorder'
Global Const $DrawAllBorders = 'DrawLeftBorder | DrawTopBorder | DrawRightBorder | DrawBottomBorder' ; не понял, как должна выглядеть эта строка
$tFlags = DllStructCreate($tagFLAGS)


Далее, если структуру $tFlags вставить на место, то цветом уже не получается управлять:

Код:
DllStructSetData($tPolicy, 'AccentFlags', DllStructGetData($tFlags, 'DrawLeftBorder'))


Короче, темный лес)) Прошу помощи, плиз)

Исходник примера полностью:

Код:
; ===============================================================================================================================
; Make the windows 10 taskbar translucent (blur)
; https://autohotkey.com/boards/viewtopic.php?f=6&t=26752
; ===============================================================================================================================

/*
TaskBar_SetAttr(option, color)
option -> 0 = off
          1 = gradient    (+color)
          2 = transparent (+color)
          3 = blur
color  -> ABGR (alpha | blue | green | red) 0xffd7a78f
*/

TaskBar_SetAttr(accent_state := 0, gradient_color := "0x01000000")
{
    static init, hTrayWnd, ver := DllCall("GetVersion") & 0xff < 10
    static pad := A_PtrSize = 8 ? 4 : 0, WCA_ACCENT_POLICY := 19

    if !(init) {
        if (ver)
            throw Exception("Minimum support client: Windows 10", -1)
        if !(hTrayWnd := DllCall("user32\FindWindow", "str", "Shell_TrayWnd", "ptr", 0, "ptr"))
            throw Exception("Failed to get the handle", -1)
        init := 1
    }

    accent_size := VarSetCapacity(ACCENT_POLICY, 16, 0)
    NumPut((accent_state > 0 && accent_state < 4) ? accent_state : 0, ACCENT_POLICY, 0, "int")

    if (accent_state >= 1) && (accent_state <= 2) && (RegExMatch(gradient_color, "0x[[:xdigit:]]{8}"))
        NumPut(gradient_color, ACCENT_POLICY, 8, "int")

    VarSetCapacity(WINCOMPATTRDATA, 4 + pad + A_PtrSize + 4 + pad, 0)
    && NumPut(WCA_ACCENT_POLICY, WINCOMPATTRDATA, 0, "int")
    && NumPut(&ACCENT_POLICY, WINCOMPATTRDATA, 4 + pad, "ptr")
    && NumPut(accent_size, WINCOMPATTRDATA, 4 + pad + A_PtrSize, "uint")
    if !(DllCall("user32\SetWindowCompositionAttribute", "ptr", hTrayWnd, "ptr", &WINCOMPATTRDATA))
        throw Exception("Failed to set transparency / blur", -1)
    return true
}

; ===============================================================================================================================

TaskBar_SetAttr(1, 0xc1e3c791)    ; <- Set gradient    with color 0xd7a78f ( rgb = 0x91c7e3 ) and alpha 0xc1
sleep 3000
TaskBar_SetAttr(2, 0xa1e3c791)    ; <- Set transparent with color 0xd7a78f ( rgb = 0x91c7e3 ) and alpha 0xa1
sleep 3000
TaskBar_SetAttr(2)                ; <- Set transparent
sleep 3000
TaskBar_SetAttr(3)                ; <- Set blur
sleep 3000
TaskBar_SetAttr(0)                ; <- Set standard value
ExitApp

/*
Since clicking on Win-Start will reset the taskbar, it will be the best solution to use a SetTimer with x ms to set the Attribute
#NoEnv
#Persistent
#SingleInstance Force
SetBatchLines -1
SetTimer, UPDATE_TASKBAR, 100
return
UPDATE_TASKBAR:
    TaskBar_SetAttr(3)
return
*/


; ===============================================================================================================================

/*
Shell_TrayWnd             -> Main TaskBar
Shell_SecondaryTrayWnd    -> 2nd  TaskBar (on multiple monitors)
*/

/* C++ ==========================================================================================================================
BOOL GetWindowCompositionAttribute(
    _In_    HWND hWnd,
    _Inout_ WINDOWCOMPOSITIONATTRIBDATA* pAttrData
);
BOOL SetWindowCompositionAttribute(
    _In_    HWND hWnd,
    _Inout_ WINDOWCOMPOSITIONATTRIBDATA* pAttrData
);
typedef struct _WINDOWCOMPOSITIONATTRIBDATA {
    WINDOWCOMPOSITIONATTRIB Attrib;
    PVOID                   pvData;
    SIZE_T                  cbData;
} WINDOWCOMPOSITIONATTRIBDATA;
typedef enum _WINDOWCOMPOSITIONATTRIB {
    WCA_UNDEFINED = 0,
    WCA_NCRENDERING_ENABLED = 1,
    WCA_NCRENDERING_ENABLED = 1,
    WCA_NCRENDERING_POLICY = 2,
    WCA_TRANSITIONS_FORCEDISABLED = 3,
    WCA_ALLOW_NCPAINT = 4,
    WCA_CAPTION_BUTTON_BOUNDS = 5,
    WCA_NONCLIENT_RTL_LAYOUT = 6,
    WCA_FORCE_ICONIC_REPRESENTATION = 7,
    WCA_EXTENDED_FRAME_BOUNDS = 8,
    WCA_HAS_ICONIC_BITMAP = 9,
    WCA_THEME_ATTRIBUTES = 10,
    WCA_NCRENDERING_EXILED = 11,
    WCA_NCADORNMENTINFO = 12,
    WCA_EXCLUDED_FROM_LIVEPREVIEW = 13,
    WCA_VIDEO_OVERLAY_ACTIVE = 14,
    WCA_FORCE_ACTIVEWINDOW_APPEARANCE = 15,
    WCA_DISALLOW_PEEK = 16,
    WCA_CLOAK = 17,
    WCA_CLOAKED = 18,
    WCA_ACCENT_POLICY = 19,
    WCA_FREEZE_REPRESENTATION = 20,
    WCA_EVER_UNCLOAKED = 21,
    WCA_VISUAL_OWNER = 22,
    WCA_LAST = 23
} WINDOWCOMPOSITIONATTRIB;
typedef struct _ACCENT_POLICY {
    ACCENT_STATE AccentState;
    DWORD        AccentFlags;
    DWORD        GradientColor;
    DWORD        AnimationId;
} ACCENT_POLICY;
typedef enum _ACCENT_STATE {
    ACCENT_DISABLED = 0,
    ACCENT_ENABLE_GRADIENT = 1,
    ACCENT_ENABLE_TRANSPARENTGRADIENT = 2,
    ACCENT_ENABLE_BLURBEHIND = 3,
    ACCENT_INVALID_STATE = 4
} ACCENT_STATE;
_ACCENT_FLAGS {
    DrawLeftBorder = 0x20,
    DrawTopBorder = 0x40,
    DrawRightBorder = 0x80,
    DrawBottomBorder = 0x100,
    DrawAllBorders = (DrawLeftBorder | DrawTopBorder | DrawRightBorder | DrawBottomBorder)
}
============================================================================================================================== */

TaskBar_SetAttr.ahk
 
Автор
M

musicstashall

Знающий
Сообщения
322
Репутация
7
Prog сказал(а):
musicstashall [?]
Пошу помощи создать структуру _ACCENT_FLAGS:
Кто сказал что это структура? Судя по коду это перечисление констант.

Ну судя по моему лепету должно быть видно, что для меня это неосвоенная территория)) Вы не могли бы помочь?? Как употребить данные константы в структуре?
 

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
musicstashall [?]
Как употребить данные константы в структуре?
Находите употребление и вписываете. Например, там где в c+ коде DrawBottomBorder в autoit будет 0x100

А что бы не делать таких "магических" цифер, и гадать что они означают, то делается константа и присваивается значение.
И дальше в коде вместо цифр - подставляете константу.

[?]
; не понял, как должна выглядеть эта строка
Какой вы не догадливый :smile:

Смотри как работает логика, вот у вас есть сгруппированные числа, каждому числу есть свое имя,
DrawLeftBorder = 0x20,
DrawTopBorder = 0x40,
DrawRightBorder = 0x80,
DrawBottomBorder = 0x100,
DrawAllBorders = (DrawLeftBorder | DrawTopBorder | DrawRightBorder | DrawBottomBorder)
Эти числа переводятся, неожиданно да. Так первая переводится как РисоватьЛевуюГраницу, дальше = РисоватьВерхнююГраницу
Так, теперь переводим последнюю DrawAllBorders - РисоватьВсеГраницы
Как нарисовать все границы? Ответ очень просто, нужно нарисовать верхнюю, правую, нижнюю и левую, т.е все четыре.
Поэтому нужно сложить все числа для этих границ. Но ненадо складывать их через +, т.к такие числа складываются через BitOr.
 
Автор
M

musicstashall

Знающий
Сообщения
322
Репутация
7
Ну хорошо, сложили, чего тут сложного)) А куда эту переменную ставить то??? На место AccentFlags? Вот, делаю так, но при этом цвет уже не управляется, остается по умолчанию:

Код:
Global Const $DrawLeftBorder = 0x20
Global Const $DrawTopBorder = 0x40
Global Const $DrawRightBorder = 0x80
Global Const $DrawBottomBorder = 0x100
Global Const $DrawAllBorders = BitOr(BitOr($DrawLeftBorder, $DrawRightBorder), BitOr($DrawTopBorder, $DrawBottomBorder))

Func _SetWindowCompositionAttribute($HWND, $tOptions, $tWinCompattrData)
	DllStructSetData($tPolicy, 'AccentState', DllStructGetData($tOptions, 'Appearance'))
	DllStructSetData($tPolicy, 'AccentFlags', $DrawAllBorders)
	DllStructSetData($tPolicy, 'GradientColor', DllStructGetData($tOptions, 'Color'))
	DllStructSetData($tPolicy, 'AnimationId', 0)
	DllStructSetData($tWinCompattrData, 'pData', DllStructGetPtr($tPolicy))
	DllStructSetData($tWinCompattrData, 'ulDataSize', DllStructGetSize($tPolicy))
	Local $aResult = DllCall("user32.dll", "bool", "SetWindowCompositionAttribute", "hwnd", $hWnd, "ptr", DllStructGetPtr($tWinCompattrData))
	If @error Then Return SetError(@error, @extended, 0)
	Return $aResult[0]
EndFunc
;==============================================
;Задаем структуру

Func SetStructure($iColor, $hWnd)
	$tWinCompattrData.nAttribute = $WCA_ACCENT_POLICY
	If $ColorPrevalence = 1 Then
		If $EnableTransparency = 1 Then
			$tOptions.Color = $Alpha & $iColor
			$tOptions.Appearance = $AccentState ;$ACCENT_ENABLE_TRANSPARENTGRADIENT
		ElseIf $EnableTransparency = 0 Then
			$tOptions.Color = '0xFF' & $iColor
			$tOptions.Appearance = $ACCENT_ENABLE_GRADIENT	
		EndIf
	ElseIf $ColorPrevalence = 0 Then
		If $EnableTransparency = 1 Then
			$tOptions.Color = $Alpha & '000000'
			$tOptions.Appearance = $AccentState ;$ACCENT_ENABLE_TRANSPARENTGRADIENT
		ElseIf $EnableTransparency = 0 Then
			$tOptions.Color = '0xFF000000'
			$tOptions.Appearance = $ACCENT_ENABLE_GRADIENT	
		EndIf	
	EndIf
	_SetWindowCompositionAttribute($HWND, $tOptions, $tWinCompattrData)
EndFunc
 

Garrett

Модератор
Локальный модератор
Сообщения
3,999
Репутация
967
Код:
DrawAllBorders = (DrawLeftBorder | DrawTopBorder | DrawRightBorder | DrawBottomBorder)
Код:
Global Const $DrawAllBorders = BitOr($DrawLeftBorder, $DrawRightBorder, $DrawTopBorder, $DrawBottomBorder)
 
Автор
M

musicstashall

Знающий
Сообщения
322
Репутация
7
Понял, что в представленном куске кода не ясно как управлять бордюрами, и вам неизвестно, придется искать документацию (которой официально нет), или примеры... :stars:


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

Нашел какое-то описание, но там ни слова про бордюры: GetWindowCompositionAttribute
Я потерян...
 

Garrett

Модератор
Локальный модератор
Сообщения
3,999
Репутация
967
musicstashall [?]
и вам неизвестно
Я указал вам на ошибку. Что касаемо задачи в целом, попробуйте так.
Код:
#include <GUIConstants.au3>
#include <WinAPIEx.au3>

$hWnd = GUICreate("Set Window Composition Attribute", 800, 600)
GUISetBkColor(0x000000)

GUISetState()

_WinAPI_SetWindowCompositionAttribute($hWnd)
If @error Then
   ConsoleWrite(StringFormat('>> _WinAPI_SetWindowCompositionAttribute: error code (%d) - error message (%s)\n', _WinAPI_GetLastError(), _WinAPI_GetLastErrorMessage()))
EndIf

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


Func _WinAPI_SetWindowCompositionAttribute($h_Wnd, $b_Enable = True)

   Const $WCA_ACCENT_POLICY = 19

   $p_AccentPolicy = DllStructCreate("int AccentState; int AccentFlags; int GradientColor; int AnimationId")
   $P_AttrData = DllStructCreate("dword Attribute; ptr DataBuffer; ulong Size")
   $p_AccentPolicy.AccentState = $b_Enable ? 3 : 0
   $P_AttrData.Attribute = $WCA_ACCENT_POLICY
   $P_AttrData.DataBuffer = DllStructGetPtr($p_AccentPolicy)
   $P_AttrData.Size = DllStructGetSize($p_AccentPolicy)

   $b_Ret = DllCall("user32.dll", "bool", "SetWindowCompositionAttribute", "hwnd", $h_Wnd, "ptr", DllStructGetPtr($p_AttrData))[0]
   If Not $b_Ret Then
	  Return SetError(1, 0, 0)
   EndIf

   Return SetError(0, 0, $b_Ret)
EndFunc ;==> _WinAPI_SetWindowCompositionAttribute
 
Автор
M

musicstashall

Знающий
Сообщения
322
Репутация
7
Ну этот вариант изначально известен, с него всё и начиналось)) Но ведь кроме блюра еще неоходимо задать цвет.


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

Вот здесь ребята сталкиваются с такой же проблемой, и ответов нет ссылка


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

Вот здесь, похоже, кое-что нашел, буду разбираться: Enable Windows 10 Aero Glass a.k.a Blur Behind in our Delphi project. Дополнительно ко всему устанавливают еще и стиль к бордюрам. Подключайтесь тоже, если не лень, хочу победить тему)
 

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
musicstashall
Вы запускали этот TaskBar_SetAttr.ahk скрипт? Он работает?
 
Автор
M

musicstashall

Знающий
Сообщения
322
Репутация
7
Эти скрипты работают с таскбаром, та задача уже решена. Сейчас пробуем идти дальше, смотрим, как работает с окнами. Не думал я, что здесь вылезет такой баг с бордюрами. Что касается приведенного мной куска кода, то предоставлено в том виде, в каком найдено.


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

Вот жеж, нашел продолжение того куска, ура. Но поможет ли это нам:

Код:
using System;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Interop;
using EarTrumpet.Services;

namespace EarTrumpet.Extensions
{
    static class BlurWindowExtensions
    {
        static class Interop
        {
            [DllImport("user32.dll")]
            internal static extern int SetWindowCompositionAttribute(IntPtr hwnd, ref WindowCompositionAttribData data);

            [StructLayout(LayoutKind.Sequential)]
            internal struct WindowCompositionAttribData
            {
                public WindowCompositionAttribute Attribute;
                public IntPtr Data;
                public int SizeOfData;
            }

            [StructLayout(LayoutKind.Sequential)]
            internal struct AccentPolicy
            {
                public AccentState AccentState;
                public AccentFlags AccentFlags;
                public int GradientColor;
                public int AnimationId;
            }

            [Flags]
            internal enum AccentFlags
            {
                // ...
                DrawLeftBorder = 0x20,
                DrawTopBorder = 0x40,
                DrawRightBorder = 0x80,
                DrawBottomBorder = 0x100,
                DrawAllBorders = (DrawLeftBorder | DrawTopBorder | DrawRightBorder | DrawBottomBorder)
                // ...
            }

            internal enum WindowCompositionAttribute
            {
                // ...
                WCA_ACCENT_POLICY = 19
                // ...
            }

            internal enum AccentState
            {
                ACCENT_DISABLED = 0,
                ACCENT_ENABLE_GRADIENT = 1,
                ACCENT_ENABLE_TRANSPARENTGRADIENT = 2,
                ACCENT_ENABLE_BLURBEHIND = 3,
                ACCENT_INVALID_STATE = 4
            }
        }

        public static void EnableBlur(this Window window)
        {
            if (SystemParameters.HighContrast)
            {
                return; // Blur is not useful in high contrast mode
            }

            SetAccentPolicy(window, Interop.AccentState.ACCENT_ENABLE_BLURBEHIND);
        }

        public static void DisableBlur(this Window window)
        {
            SetAccentPolicy(window, Interop.AccentState.ACCENT_DISABLED);
        }

        private static void SetAccentPolicy(Window window, Interop.AccentState accentState)
        {
            var windowHelper = new WindowInteropHelper(window);

            var accent = new Interop.AccentPolicy();
            accent.AccentState = accentState;
            accent.AccentFlags = GetAccentFlagsForTaskbarPosition();

            var accentStructSize = Marshal.SizeOf(accent);

            var accentPtr = Marshal.AllocHGlobal(accentStructSize);
            Marshal.StructureToPtr(accent, accentPtr, false);

            var data = new Interop.WindowCompositionAttribData();
            data.Attribute = Interop.WindowCompositionAttribute.WCA_ACCENT_POLICY;
            data.SizeOfData = accentStructSize;
            data.Data = accentPtr;

            Interop.SetWindowCompositionAttribute(windowHelper.Handle, ref data);

            Marshal.FreeHGlobal(accentPtr);
        }

        private static Interop.AccentFlags GetAccentFlagsForTaskbarPosition()
        {
            var flags = Interop.AccentFlags.DrawAllBorders;

            switch(TaskbarService.GetWinTaskbarState().TaskbarPosition)
            {
                case TaskbarPosition.Top:
                    flags &= ~Interop.AccentFlags.DrawTopBorder;
                    break;

                case TaskbarPosition.Bottom:
                    flags &= ~Interop.AccentFlags.DrawBottomBorder;
                    break;

                case TaskbarPosition.Left:
                    flags &= ~Interop.AccentFlags.DrawLeftBorder;
                    break;

                case TaskbarPosition.Right:
                    flags &= ~Interop.AccentFlags.DrawRightBorder;
                    break;
            }

            return flags;
        }
    }
}


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

Ближе к цели. Сделал таким образом:

Код:
Func _SetWindowCompositionAttribute($HWND, $tOptions, $tWinCompattrData)
	$tRect = _WinAPI_GetWindowRect($hWnd)
	$DrawLeftBorder =  DllStructGetData($tRect, "Left") 
	$DrawTopBorder = DllStructGetData($tRect, "Top") 
	$DrawRightBorder = DllStructGetData($tRect, "Right") 
	$DrawBottomBorder = DllStructGetData($tRect, "Bottom")
	$AccentFlags = BitOr($DrawLeftBorder, $DrawRightBorder, $DrawTopBorder, $DrawBottomBorder)
	DllStructSetData($tPolicy, 'AccentState', DllStructGetData($tOptions, 'Appearance'))
	DllStructSetData($tPolicy, 'AccentFlags', $AccentFlags)
	DllStructSetData($tPolicy, 'GradientColor', DllStructGetData($tOptions, 'Color'))
	DllStructSetData($tPolicy, 'AnimationId', 0)
	DllStructSetData($tWinCompattrData, 'pData', DllStructGetPtr($tPolicy))
	DllStructSetData($tWinCompattrData, 'ulDataSize', DllStructGetSize($tPolicy))
	Local $aResult = DllCall("user32.dll", "bool", "SetWindowCompositionAttribute", "hwnd", $hWnd, "ptr", DllStructGetPtr($tWinCompattrData))
	If @error Then Return SetError(@error, @extended, 0)
	Return $aResult[0]
EndFunc


В итоге, слева бордюр блюра остался прежним, около 10 пикс, снизу — ушел за пределы экрана, справа — примерно 300 пикс. Уже что-то)) Цвет при этом уже регулируется, можно задавать величину альфы. Теперь нужно поиграть с размерами...
ПС: почему рект блюра нарисовался с такими размерами, я в недоумении)))
 

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
musicstashall
Последний код - глупость, вы взяли размер окна, а потом почему то использовали это как $AccentFlags
 
Верх