質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.49%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Win32 API

Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

1回答

1231閲覧

UpdateLayeredWindowによる透過

Weapon

総合スコア106

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Win32 API

Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2019/04/28 15:37

編集2019/04/29 08:37

前提・実現したいこと

以前SetLayeredWindowAttibutes func.においての透過処理はしましたがOpenGLの描画等に透過をかけれるよう,より詳細にAlfa値を使って描画したいと思いUpdateLayeredWindow func.を使おうとサンプル等を読み作ってみましたがうまく動作しません.DeviceContextの取り方が悪いのかAlpha値が0になっているのか一通り見てみたつもりですが関数自体は成功してもウィンドウに効きません.WS_EX_LAYERED無しの動作確認はしました.よろしくお願いします.

###追記
指摘をもとに多少の修正と引数の変更を行いましたが上手くいきません.一応動作するサンプルも追記しましたがスクリーンDCを使用しなくても動いてしまうらしいので気をつけます.しかし動作するサンプルのUpdateLayeredWindow func.の第四引数のウィンドウの座標を変更したりNULLにしたりすると表示がされない上タスクバーにアイコンができないなど挙動が理解できません.

コード(修正して追記)

指摘をもとに修正
UpdateLayeredWindow func.は130行目付近

C

1#define UNICODE 2 3#include <windows.h> 4 5LRESULT CALLBACK WindowProc(HWND, UINT, WPARAM, LPARAM); 6 7const wchar_t CLASS_NAME[] = L"SAMPLE_UpdateLayeredWindow"; 8 9HINSTANCE hGlobalInstance; 10 11int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR nCmdLine, _In_ int nCmdShow) { 12 UNREFERENCED_PARAMETER(hPrevInstance); 13 UNREFERENCED_PARAMETER(nCmdLine); 14 15 hGlobalInstance = hInstance; 16 17 WNDCLASSEX wc = { 18 sizeof(WNDCLASSEX), CS_VREDRAW | CS_HREDRAW, WindowProc, 19 0, 0, hInstance, 20 NULL, (HCURSOR)LoadCursor(NULL, IDC_ARROW), (HBRUSH)GetStockObject(WHITE_BRUSH), 21 NULL, CLASS_NAME, NULL 22 }; 23 24 RegisterClassEx(&wc); 25 26 HWND hwnd = CreateWindowEx( 27 WS_EX_LAYERED, CLASS_NAME, L"Template", WS_OVERLAPPEDWINDOW, 28 50, 50, 960, 525, 29 NULL, NULL, hInstance, NULL 30 ); 31 32 ShowWindow(hwnd, nCmdShow); 33 UpdateWindow(hwnd); 34 35 MSG msg = {}; 36 37 while (GetMessage(&msg, NULL, 0, 0) > 0) { 38 TranslateMessage(&msg); 39 DispatchMessage(&msg); 40 } 41 42 return (int)msg.wParam; 43} 44 45LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { 46 static RECT crc; 47 static int iWidth = 0; 48 static int iHeight = 0; 49 50 static HDC hbufdc; 51 static HBITMAP hbmp; 52 53 static BLENDFUNCTION bf = { 54 AC_SRC_OVER, 0, 0x7f, AC_SRC_ALPHA 55 }; 56 57 static SIZE wsz = { 0 }; 58 static POINT pt = { 0 }; 59 60 switch (uMsg) { 61 case WM_ERASEBKGND: 62 return -1; 63 64 case WM_CREATE: 65 { 66 HDC hmdc = GetDC(hwnd); 67 hbufdc = CreateCompatibleDC(hmdc); 68 ReleaseDC(0, hmdc); 69 } 70 break; 71 72 case WM_PAINT: 73 { 74 PAINTSTRUCT ps = {}; 75 HDC hdc = BeginPaint(hwnd, &ps); 76 77 if (BitBlt(hdc, 0, 0, iWidth, iHeight, hbufdc, 0, 0, SRCCOPY | CAPTUREBLT) == FALSE)MessageBox(hwnd, L"BitBlt ERROR", L"WM_PAINT ERROR", MB_OK); 78 SetBkMode(hdc, TRANSPARENT); 79 80 EndPaint(hwnd, &ps); 81 } 82 break; 83 84 case WM_SIZE: 85 { 86 GetClientRect(hwnd, &crc); 87 int crWidth = crc.right - crc.left; 88 int crHeight = crc.bottom - crc.top; 89 if ((crWidth != iWidth) || (crHeight != iHeight)) { 90 iWidth = crWidth; 91 iHeight = crHeight; 92 93 wsz.cx = crWidth; 94 wsz.cy = crHeight; 95 96 /* Create BITMAP */ 97 if (hbmp != NULL)DeleteObject(hbmp); 98 99 void* pv; 100 BITMAPINFO bmi = { 101 sizeof(BITMAPINFOHEADER), iWidth, iHeight, 1, 32, BI_RGB, 0, 0, 0, 0, 0, 0 102 }; 103 104 hbmp = CreateDIBSection(hbufdc, &bmi, DIB_RGB_COLORS, &pv, NULL, 0); 105 106 if (hbmp == NULL) { 107 if (iWidth != 0 && iHeight != 0) { 108 MessageBox(hwnd, L"CreateDIBSection ERROR", L"WM_SIZE ERROR", MB_OK); 109 } 110 break; 111 } 112 113 DWORD* lpdw = (DWORD*)pv; 114 int mdsize = iWidth * iHeight; 115 for (int i = 0; i < mdsize; i++)lpdw[i] = 0x7fff00ff; 116 117 SelectObject(hbufdc, hbmp); 118 /* END Create BITMAP */ 119 120 /* TRANSPARENT Process */ 121 RECT wrc; 122 GetWindowRect(hwnd, &wrc); 123 pt.x = wrc.left; 124 pt.y = wrc.top; 125 126 HDC sdc = GetDC(NULL); 127 if (UpdateLayeredWindow(hwnd, sdc, NULL, &wsz, hbufdc, &pt, 0, &bf, ULW_ALPHA) == FALSE) { 128 MessageBox(hwnd, L"Update ERROR", L"WM_SIZE ERROR", MB_OK); 129 DestroyWindow(hwnd); 130 } 131 ReleaseDC(0, sdc); 132 /* END TRANSPARENT Process */ 133 InvalidateRect(hwnd, NULL, FALSE); 134 } 135 } 136 break; 137 138 case WM_DESTROY: 139 DeleteDC(hbufdc); 140 DeleteObject(hbmp); 141 PostQuitMessage(0); 142 return 0; 143 } 144 145 return DefWindowProc(hwnd, uMsg, wParam, lParam); 146} 147

###参考にしているサンプル(追記)

C

1#define UNICODE 2#include <windows.h> 3 4LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); 5ATOM InitApp(HINSTANCE); 6BOOL InitInstance(HINSTANCE, int); 7 8LPCWSTR szClassName = L"layer01"; //ウィンドウクラス 9HINSTANCE hInst; 10 11HBITMAP hBmpGra; //グラデーションを格納 12 13int WINAPI WinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst, 14 LPSTR lpsCmdLine, int nCmdShow) { 15 MSG msg; 16 BOOL bRet; 17 18 hInst = hCurInst; 19 if (!InitApp(hCurInst)) 20 return FALSE; 21 if (!InitInstance(hCurInst, nCmdShow)) 22 return FALSE; 23 while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0) { 24 if (bRet == -1) { 25 break; 26 } 27 else { 28 TranslateMessage(&msg); 29 DispatchMessage(&msg); 30 } 31 } 32 return (int)msg.wParam; 33} 34 35//ウィンドウ・クラスの登録 36ATOM InitApp(HINSTANCE hInst) { 37 WNDCLASSEX wc; 38 wc.cbSize = sizeof(WNDCLASSEX); 39 wc.style = CS_HREDRAW | CS_VREDRAW; 40 wc.lpfnWndProc = WndProc; //プロシージャ名 41 wc.cbClsExtra = 0; 42 wc.cbWndExtra = 0; 43 wc.hInstance = hInst;//インスタンス 44 wc.hIcon = (HICON)LoadImage(NULL, 45 MAKEINTRESOURCE(IDI_APPLICATION), 46 IMAGE_ICON, 47 0, 48 0, 49 LR_DEFAULTSIZE | LR_SHARED); 50 wc.hCursor = (HCURSOR)LoadImage(NULL, 51 MAKEINTRESOURCE(IDC_ARROW), 52 IMAGE_CURSOR, 53 0, 54 0, 55 LR_DEFAULTSIZE | LR_SHARED); 56 wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); 57 wc.lpszMenuName = NULL; //メニュー名 58 wc.lpszClassName = szClassName; 59 wc.hIconSm = (HICON)LoadImage(NULL, 60 MAKEINTRESOURCE(IDI_APPLICATION), 61 IMAGE_ICON, 62 0, 63 0, 64 LR_DEFAULTSIZE | LR_SHARED); 65 66 return (RegisterClassEx(&wc)); 67} 68 69//ウィンドウの生成 70BOOL InitInstance(HINSTANCE hInst, int nCmdShow) { 71 HWND hWnd; 72 73 hWnd = CreateWindowEx(WS_EX_LAYERED | WS_EX_TOPMOST | WS_EX_TOOLWINDOW, 74 szClassName, 75 L"Test Layer Window", //Title 76 WS_POPUP, 77 50, //X 78 50, //Y 79 960, //width 80 520, //height 81 NULL, //hWnd 82 NULL, //Menu 83 hInst, 84 NULL); 85 if (!hWnd) 86 return FALSE; 87 ShowWindow(hWnd, nCmdShow); 88 UpdateWindow(hWnd); 89 return TRUE; 90} 91 92//グラデーションのBitmapの作成 93HBITMAP make_gradation(HWND hWnd, unsigned height, unsigned width, BYTE _r, BYTE _g, BYTE _b) { 94 void* lpBits; 95 96 BITMAPINFO bi = { 97 sizeof(BITMAPINFOHEADER), 960, 520, 1, 32, BI_RGB, 0, 0, 0, 0, 0, 0 98 }; 99 100 HDC hdc = GetDC(hWnd); 101 HBITMAP hbmp = CreateDIBSection(hdc, (BITMAPINFO*)& bi, DIB_RGB_COLORS, 102 (void**)& lpBits, NULL, (DWORD)0); 103 ReleaseDC(hWnd, hdc); 104 105 DWORD* lpdw = (DWORD*)lpBits; 106 int mdsize = 960 * 520; 107 for (int i = 0; i < mdsize; i++)lpdw[i] = 0x7fff00ff; 108 109 return hbmp; 110}; 111 112 113//ウィンドウプロシージャ 114LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { 115 int id; 116 HDC hdc, hdc_mem, hsdc; 117 HBRUSH hBrush; 118 PAINTSTRUCT ps; 119 LPCWSTR szBuf = L"Test Layer Window"; 120 BITMAP bmp_info; 121 HBITMAP hBmp; 122 int wx, wy; 123 const COLORREF col = RGB(0, 255, 0); 124 HGDIOBJ hOldObj; 125 BLENDFUNCTION blend; 126 POINT wndPos; 127 SIZE wndSize; 128 RECT rc; 129 POINT po; 130 131 switch (msg) { 132 case WM_CREATE: 133 hBmpGra = make_gradation(hWnd, 520, 960, 0, 255, 60); 134 135 case WM_PAINT: 136 hsdc = GetDC(hWnd); 137 hdc = BeginPaint(hWnd, &ps); 138 hdc_mem = CreateCompatibleDC(hdc); 139 SelectObject(hdc_mem, hBmpGra); 140 BitBlt(hdc, 0, 0, 960, 520, hdc_mem, 0, 0, SRCCOPY | CAPTUREBLT); 141 142 wndSize.cx = 960; wndSize.cy = 520; 143 po.x = po.y = 0; 144 blend.BlendOp = AC_SRC_OVER; 145 blend.BlendFlags = 0; 146 blend.SourceConstantAlpha = 0xff; 147 blend.AlphaFormat = AC_SRC_ALPHA; 148 UpdateLayeredWindow(hWnd, hsdc, nullptr, &wndSize, hdc_mem, &po, 0, &blend, ULW_ALPHA); 149 150 DeleteDC(hdc_mem); 151 SetBkMode(hdc, TRANSPARENT); 152 EndPaint(hWnd, &ps); 153 ReleaseDC(0, hsdc); 154 break; 155 case WM_CLOSE: 156 id = MessageBox(hWnd, 157 L"終了してもよろしいですか", 158 L"確認", 159 MB_YESNO | MB_ICONQUESTION); 160 if (id == IDYES) 161 DestroyWindow(hWnd); 162 break; 163 case WM_RBUTTONDOWN: 164 SendMessage(hWnd, WM_CLOSE, 0, 0); 165 break; 166 case WM_LBUTTONDOWN: 167 PostMessage(hWnd, WM_NCLBUTTONDOWN, (WPARAM)HTCAPTION, lp); 168 break; 169 case WM_DESTROY: 170 PostQuitMessage(0); 171 break; 172 default: 173 return (DefWindowProc(hWnd, msg, wp, lp)); 174 } 175 return 0; 176}

補足情報

Windows10 Pro
VisualStudio2019 Community

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

UpdateLayeredWindow に渡す 2 番目の引数が誤っています。マイクロソフトのドキュメントに記載のある通り、これはスクリーン DC でなければなりません。スクリーン DC は GetDC に NULL を渡して取得した DC になります。また、初回呼び出しで 4 番目のサイズを NULL にすることはできません。ヘルプからは読み取りにくいですがサイズが変わらなければ NULL でも良いと記載されていますが、初回は必ず指定する必要があります。

BitBlt には SRCCPY 以外に CAPTUREBLT も指定しておくべきです。WS_EX_LAYERED スタイルが指定されたウィンドウの DC に対して BitBlt する場合はつけておくのが無難です。

以上の話からして WM_PAINT で処理する必要があんまりありません。WM_SIZE の段階で必要な情報がそろっているので、WM_SIZE で処理してしまった方が簡単です。とは言っても、DWM 環境下では WM_PAINT はそれほど頻繁に呼び出されるわけではありませんが。


参考にしているサンプルの WM_PAINT 処理で GetDCしている際にはウインドウハンドルを渡していますが、ReleaseDCでは 0 を渡しています。これは明らかにサンプルの誤りですね。GetDC 際にも 0 を渡す必要があります。


修正後のソースも見ましたが、UpdateLayeredWindow に渡す引数がサンプルとは異なる部分がまだあります。そこを直すととりあえず動作するようになるかと思います。この辺の API は GetLastError でもまともな情報が取れないので、試行錯誤して使用方法を探すしかないのが厳しいところですね。

投稿2019/04/28 16:25

編集2019/04/29 09:17
atata0319

総合スコア881

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Weapon

2019/04/29 08:37

追記しました.よろしかったらお願いします.
Weapon

2019/04/29 11:31

POINT struct.に{0,0}をいれると動作しますがこのことでよろしいでしょうか? リファレンスの"A pointer to a structure that specifies the location of the layer in the device context."のところの解釈がわからないのですけどこれはウィンドウの位置とは別ということでしょうか
atata0319

2019/04/29 14:31

> POINT struct.に{0,0}をいれると動作しますがこのことでよろしいでしょうか? はい。問題ありません。 この文面での the device context とは 5 番目の引数 hdcSrc を指します。hdcSrc 側の説明として A handle to a DC for the surface that defines the layered window. と記述されており、これはレイヤーウィンドウを定義する DC を指定すると解釈されます。この DC のうちどこからレイヤーウィンドウとして使用するかどうかを指定するって解釈になりますね。 あんまり多くはないと思いますが、ウィンドウのサイズ以上のビットマップを用意した場合に、その位置を指定するためのパラメータというところです。このサンプルではウィンドウのサイズに合わせて作成してあるので、原点 (0, 0) で問題ないというところですね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問