약 1년 전 윈도우즈 블로그에 아래와 같은 글 하나가 등록되어있었다.
We’ve also heard loud in clear that many Windows Insiders want to see Aero Glass from Windows 7 make a comeback. We’ve been working out how to satisfy this request, and are trying some things out with this build to see how you like them. We’re running a little A/B test with this build. 50% of you will normal transparency on the Start menu and taskbar while the other 50% will see a blur effect on the Start menu and taskbar (like frosted glass). If Windows Insiders really like the blur effect, we will add it to more areas and even consider making it the default instead of standard transparency. Which one did you get? Send us feedback about it via the Windows Feedback app!
어쩐지 어느 순간부터 단순 반투명이 아닌 시작 메뉴의 배경에 번짐효과가 은근슬적 적용되었다 싶었다.
무려 1년이 지난 지금도 MSDN에는 이러한 효과를 사용하기위한 내용은 없다. 컴백이라더니 왜 공개 안하는지는 모르겠는데… 그냥 예상되는거라면 너도나도 남용할거같아서? 그래도 능력자들이 리버스 엔지니어링을했는지 이것의 적용법을 WPF, Delphi XE버전으로 남겨진 글이 있다.
WPF: http://withinrafael.com/adding-the-aero-glass-blur-to-your-windows-10-apps/
Delphi: http://stackoverflow.com/questions/32724187/how-do-you-set-the-glass-blend-colour-on-windows-10
문제는 이게 C로 정의된걸 꼬박 하루동안 찾지못해 엉뚱한 삽질을 했다는거… 역시나 중국은 무섭게도 C언어로 함수 원형과 구조체들을 정리한것이 나왔다. (Microsoft에서 공개한 문서도 없는데 저런걸 어떻게 다 찾아내서 이름까지도 정하는건지 신기하다.)
C: https://git.oschina.net/ysc3839/codes/djcx0y3b9a5pmtrzgq6ki (여담이지만 코멘트로 달려있는 소스의 마지막 라인에 FreeLibrary(hUser); 한줄이 더 추가되어야 맞을것이다.)
처음엔 WPF 버전의 코드를 보고 C로 옮겼지만 왜인지 되어야하는데 안된다 싶었다. 저 코드를 찾기 전만해도 계속 #pragma pack(push, 1), #pragma pack(pop)을 쓰고있었고, 해당 구조체는 이러한 packing이 필요 없던것이였다(…). OS 레벨의 구조체는 packing이 일반적이라 당연히 필요한 줄 알았건만 이것이 하루 삽질하게 만들고, 그나마 다행인건 좀 더 완전하게 정의 된 C버전의 코드를 찾았다는 정도다.
암튼 현재 만들고있는 프로그램에서 정의하여 사용하는 구조체와 함수 원형은 아래와같다.
정의
enum AccentState { ACCENT_DISABLED = 0, ACCENT_ENABLE_GRADIENT = 1, ACCENT_ENABLE_TRANSPARENTGRADIENT = 2, ACCENT_ENABLE_BLURBEHIND = 3, ACCENT_INVALID_STATE = 4 }; enum WindowCompositionAttribute { WCA_ACCENT_POLICY = 19 }; struct AccentPolicy { AccentState accentState; int accentFlags; int gradientColor; int animationId; }; struct WindowCompositionAttributeData { WindowCompositionAttribute attribute; PVOID pData; ULONG dataSize; }; typedef BOOL (WINAPI *pfnGWA)(HWND, WindowCompositionAttributeData*);
Qt 코드 일부
QLibrary user32("user32.dll"); pfnGWA setWindowAttribute = (pfnGWA)user32.resolve("SetWindowCompositionAttribute"); AccentPolicy policy; std::memset(&policy, 0, sizeof(policy)); policy.accentState = ACCENT_ENABLE_BLURBEHIND; WindowCompositionAttributeData data; data.attribute = WCA_ACCENT_POLICY; data.dataSize = sizeof(policy); data.pData = &policy; setWindowAttribute((HWND)winId(), &data); setAttribute(Qt::WA_TranslucentBackground); setWindowFlags(Qt::FramelessWindowHint);
끝.
이렇게하면 뭔가 잘 먹혀드는거같지만… 문제는 컨트롤 내 반투명 효과(?)가 쓰인 컨트롤이 있다면 컨트롤이 업데이트 될 때 마다 투명도가 점점 줄어드는 문제가있다.
단순히 바로 위 코드에서 setAttribute, setWindowFlags 두 라인만 쓰면 이러한 문제가 없지만 blur effect를 적용시키면 이런 문제가 나타난다.
이 모습에서 다이얼로그를 돌리면
이렇게 그림자 효과가 점점 짙어진다.
SetWindowCompositionAttribute가 적용되면 왜 저러는지 모르겠지만 일단 API를 사용하는 방법을 알아냈으니… 쓸지 말지를 생각 해 보고 쓰게된다면 이 투명도가 떨어지는 문제를 해결 해 봐야겠다.