初歩ですが...テキストが透過されません(Win32API)なんで・・・?

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
アバター
結城
記事: 52
登録日時: 14年前
連絡を取る:

初歩ですが...テキストが透過されません(Win32API)なんで・・・?

#1

投稿記事 by 結城 » 14年前

おひさしぶりです、Hinariです
今回、ライブラリでプログラムをしていると色々と制約が出てきたので
ライブラリなしでコードを書こうと思い
Win32APiに移植をしていると
なんだか色々と問題が起きてしまいました

そのなかで、大した問題でないように思えて原因が全然つかめなかったので
質問させていただきます

テキストを描画したのですが、なぜか文字の後ろに白い四角が描画されてしまい
テキストのみを描画することができません

...というか、何が原因で透過できていないのかさっぱりです

以下はテキストを描画している場所のコードとその描画先ウィンドウと親ウィンドウです
(関数名とか主仕様ですので見逃してくださいw)

コード:

BOOL InitApp(HINSTANCE hInst, WNDPROC WndProc, LPCWSTR szClassName)
{
	WNDCLASS wc;

	//プロシージャ名
	wc.cbCls Extra = 0; //禁止単語回避
	wc.cbWndExtra = 0;
	wc.hInstance = hInst; //インスタンス
	wc.style = CS_HREDRAW | CS_VREDRAW;
	wc.lpfnWndProc = WndProc;
	wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
	wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
	wc.lpszMenuName = NULL; //メニュー名
	wc.lpszClassName = (LPCWSTR)szClassName;
	return (RegisterClass(&wc));
} 

// 文字描画(変数引数可)
void PrintMessage(HDC hdc,LPCWSTR lpchText,int x,int y)
{
	HFONT hf01;
	static LOGFONT lf01;
	ZeroMemory(&lf01,sizeof(lf01));
	lf01.lfCharSet=DEFAULT_CHARSET;
	lf01.lfQuality=ANTIALIASED_QUALITY;
	_tcscpy(lf01.lfFaceName,_T("メイリオ"));
	hf01=CreateFontIndirect(&lf01);
	//HGDIOBJ hOldOBj = SelectObject(hdc, hFont);
	RECT rc = { x , y , 24*wcslen(lpchText) , 36 };
	SetTextColor(hdc, RGB(0,0,0));
	//SetBkColor(hdc, RGB(0xff,0xff,0xff));
	//SetBkMode(hdc, OPAQUE); 
	DrawText(hdc, lpchText, -1, &rc, DT_LEFT);
	SelectObject(hdc, hf01);
	//TextOut( hdc, x, y, lpchText, (int)_tcslen(lpchText) );
	DeleteObject( hf01 );  

}

BOOL InitInstance(HINSTANCE hInstance)
{
	HWND hWnd;

	hInst = hInstance; // グローバル変数にインスタンス処理を格納します。

	hWnd = CreateWindowEx(WS_EX_LAYERED | WS_EX_TOPMOST, szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

	// タスクバーにボタンを表示したくない場合は、次のようにする
	//hWnd = CreateWindowEx(WS_EX_LAYERED | WS_EX_TOPMOST | WS_EX_TOOLWINDOW, szWindowClass, szTitle, WS_POPUP,
	//  CW_USEDEFAULT, 0, uWidth, uHeight, NULL, NULL, hInstance, NULL);

	if (!hWnd) {
		return FALSE;
	}

	// 文字描画用のウィンドウを生成
	// 位置はメインウィンドウと同じ位置で
	RECT rc;
	GetWindowRect(hWnd, &rc);
	ghMojiWindow = CreateWindowEx(WS_EX_LAYERED | WS_EX_TOPMOST | WS_EX_TOOLWINDOW | WS_EX_TRANSPARENT,
		szWindowClass2, szTitle2, WS_POPUP,
		rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, hWnd, NULL, hInstance, NULL);

	if (!ghMojiWindow) {
		return FALSE;
	}


	ShowWindow(hWnd, SW_SHOWNORMAL);
	UpdateWindow(hWnd);

	ShowWindow(ghMojiWindow, SW_SHOWNORMAL);
	UpdateWindow(ghMojiWindow);

	// テスト的に文字を描画してみる
	HDC hdc = GetDC(ghMojiWindow);
	PrintMessage(hdc,_T("SetupInstance...Step1 - Check Through ...Okay"),10,10);
	ReleaseDC(ghMojiWindow, hdc);

	return TRUE;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message) {
		case WM_CREATE:
			{
				// PNGファイルを読み出しておく
				FILE *fp = _tfopen(_T("AIS_MainSerface700x500.png"), _T("rb"));

				if (fp == NULL) {
					MessageBox(hWnd, _T("AIS_MainSerface700x500.pngが開けません。"), _T("エラー"), MB_OK | MB_ICONSTOP);
					DestroyWindow(hWnd);
					break;
				}

				// メモリに読み込んだpngファイルを、ビットマップハンドルにする
				hBitmap = LoadPngFromFile(hWnd, fp, uWidth, uHeight);
				if (hBitmap == NULL) {
					fclose(fp);
					MessageBox(hWnd, _T("test_ulw.pngをPNGファイルとして読み込めませんでした。"), _T("エラー"), MB_OK | MB_ICONSTOP);
					DestroyWindow(hWnd);
					break;
				}

				fclose(fp);

				// ウィンドウの形状をビットマップに合わせて変更
				SetWindowPos(hWnd, 0, 0, 0, uWidth, uHeight, SWP_NOMOVE | SWP_NOZORDER);

				// ==========================
				// レイヤードウィンドウの設定
				// ==========================
				// 各種デバイスコンテキストの取得
				HDC hmemdc, hdc, hsdc;
				hsdc   = GetDC(0);                      // デスクトップのデバイスコンテキスト(色情報指定用)
				hdc    = GetDC(hWnd);                   // このウィンドウのデバイスコンテキスト
				hmemdc = CreateCompatibleDC(hdc);       // hdcの互換デバイスコンテキスト

				POINT wndPos;
				SIZE  wndSize;
				RECT  rc;

				// レイヤードウィンドウの画面位置とサイズ
				GetWindowRect(hWnd, &rc);
				wndPos.x = rc.left;
				wndPos.y = rc.top;
				wndSize.cx = uWidth;
				wndSize.cy = uHeight;

				// デバイスコンテキストにおけるレイヤの位置
				POINT po;
				po.x = po.y = 0;

				// レイヤードウィンドウの指定
				BLENDFUNCTION blend;
				blend.BlendOp = AC_SRC_OVER;
				blend.BlendFlags = 0;
				blend.SourceConstantAlpha = 255; // 不透明度(レイヤードウィンドウ全体のアルファ値)
				blend.AlphaFormat = AC_SRC_ALPHA;

				// 画像を描画をする
				HGDIOBJ hOldObj = SelectObject(hmemdc, hBitmap);
				BitBlt(hdc, 0, 0, uWidth, uHeight, hmemdc, 0, 0, SRCCOPY|CAPTUREBLT); // レイヤードウィンドウではCAPTUREBLTが必要

				// レイヤードウィンドウの位置、サイズ、形、内容、透明度を更新
				if (0 == UpdateLayeredWindow(hWnd, hsdc, &wndPos, &wndSize, hmemdc, &po, 0, &blend, ULW_ALPHA)) {
					TCHAR strErrMes[80];
					DWORD err = GetLastError();

					wsprintf(strErrMes, _T("UpdateLayeredWindow失敗:エラーコード=%d"), err);
					MessageBox(hWnd, strErrMes, _T("エラー"), MB_OK | MB_ICONSTOP);
					DestroyWindow(hWnd);
				}

				SelectObject(hmemdc, hOldObj);
				DeleteDC(hmemdc);
				ReleaseDC(hWnd, hdc);
				ReleaseDC(0, hsdc);

			}
			break;

		case WM_NCHITTEST: // ウィンドウ上のどこをマウスで掴んでも、位置を移動できるようにする
			return HTCAPTION;

		case WM_TIMER:
			break;

		case WM_MOVING: // 文字描画用ウィンドウにも同様のメッセージを伝える
			{
				LPRECT prc = (LPRECT)lParam;
				MoveWindow(ghMojiWindow, prc->left, prc->top, prc->right - prc->left, prc->bottom - prc->top, FALSE);
			}
			break;

		case WM_DESTROY:
			if (hBitmap)
				DeleteObject(hBitmap);
			PostQuitMessage(0);
			break;

		default:
			return DefWindowProc(hWnd, message, wParam, lParam);
	}
	return 0;
}

// 文字描画ウィンドウ用のウィンドウプロシージャ。基本的に何もしない。
LRESULT CALLBACK WndProc2(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message) {
		case WM_CREATE:
			// 文字描画用ウィンドウはビットマップのサイズに合わせる
			SetWindowPos(ghMojiWindow, 0, 0, 0, uWidth, uHeight, SWP_NOMOVE | SWP_NOZORDER);

			// 子ウィンドウの白部分は通過色に
			SetLayeredWindowAttributes(hWnd, RGB(0xff, 0xff, 0xff), 255, LWA_COLORKEY | LWA_ALPHA);

			// 標準フォントの取得
			//hFont = (HFONT)GetStockObject(SYSTEM_FONT);

				hInst = ((LPCREATESTRUCT)lParam)->hInstance;
				InitApp(hInst, AIS_Main_WinProc, _T("child"));
				hChdWnd = CreateWindowW(_T("child"),
					_T(" - Icais ver.01A-NANA - "),//タイトルバーにこの名前が表示されます
					WS_SYSMENU | WS_THICKFRAME | WS_CAPTION | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_EX_TOOLWINDOW, //ウィンドウの種類
					CW_USEDEFAULT, //X座標
					CW_USEDEFAULT, //Y座標
					800, //幅
					600, //高さ
					hWnd, //親ウィンドウのハンドル、親を作るときはNULL
					(HMENU)NULL, //メニューハンドル、子供のID
					hInst, //インスタンスハンドル
					NULL);
				ShowWindow(hChdWnd, SW_SHOW);
				UpdateWindow(hChdWnd);


			break;

		case WM_CLOSE: // 突然の終了禁止
			return 0;

		default:
			return DefWindowProc( hWnd, message, wParam, lParam );
	}
	return 0;
}

LRESULT CALLBACK AIS_Main_WinProc(HWND hwnd,UINT message,WPARAM wparam,LPARAM lparam)
{

	static char text[] = "Iris CreativeEntertaimentTalkSystem Type-A ProperName-NANA...";
	static char *p=text;
	static wchar_t pp;
	static wchar_t ppp[256];
	static int c=0;
	switch(message)
	{
	case    WM_CREATE:
		if(SetTimer(hwnd, ID_MYTIMER, 3, NULL) == 0)
		{
		}
		else
		{
		}
		break;
	case WM_TIMER:
		if(c>=_mbstrlen((const char*)text)){
			KillTimer(hwnd, ID_MYTIMER);
		}else{
			KillTimer(hwnd, ID_MYTIMER);
			SetTimer(hwnd, ID_MYTIMER, 3, NULL);
			cw_change(&pp,2,p);
			wcscat(ppp,&pp);
			++p;
			c++;
			InvalidateRect(hwnd,NULL,NULL);
		}
		break;
	case WM_NCHITTEST: // ウィンドウ上のどこをマウスで掴んでも、位置を移動できるようにする
		return HTCAPTION;
		break;
	case    WM_DESTROY:         /*  ウインドウの後処理         */
		AIS_Main_DestroyProc();
		break;
	case WM_PAINT:
		HBRUSH hBrush;
		PAINTSTRUCT ps;
		HDC hdc;
		hdc=BeginPaint(hwnd,&ps);
		RECT rc;
		GetClientRect(hwnd,&rc);
		hBrush = CreateSolidBrush(RGB(176,224,230));
		FillRect(hdc,&rc,hBrush);
		DeleteObject(hBrush);
		EndPaint(hwnd, &ps);
		PrintMessage(GetDC(hwnd),ppp,10,10);
		break;
	default:
		return	DefWindowProc(hwnd,message,wparam,lparam);
	}
	return  0L;

}
一応関連あるかと思ったとこをあげときました

wc.cbCls Extra = 0; ←引っかかったので禁止単語回避してます

環境は
VS2005 C++
ライブラリなし・・・なのか?(Win32APIとかともいうらしい・・・まだそんなに詳しくないです)
WinXP HomeSP3
ANGE;ART

アバター
結城
記事: 52
登録日時: 14年前
連絡を取る:

Re: 初歩ですが...テキストが透過されません(Win32API)なんで・・・?

#2

投稿記事 by 結城 » 14年前

自分で色々関数をあさっているうちに解決してしまいました・・・
どうやらSetBkModeの第二引数にTRANSPARENTを渡してやるといいようです
どうもお騒がせしました
ANGE;ART

閉鎖

“C言語何でも質問掲示板” へ戻る