UWSCでイメージを表示する

UWSCで画像を表示する方法を検討してみた。
ただ、画像を表示するだけ。

Pro版のフォームを使う

  • メリット
    • 画像だけにできる(タイトルバーを消せる)
    • 透過処理を使うと任意の形に見える
  • デメリット
    • ファイル読込みでしかできなかった(srcに「data:image/png;base64,...」指定ができなかった)


多分、使ってるIEコンポーネントのせいか?
ViewImage.uws

OPTION EXPLICIT


IFB GET_UWSC_NAME = "ViewImage.uws" THEN
	ViewImage.Show("c:\test.bmp")
	WHILE !GETKEYSTATE(VK_ESC)
		SLEEP(0.1)
	WEND
	ViewImage.Hide()	// 特に必要ではない
	ViewImage.Dispose()	// 最後にやった方が良いかも
ENDIF


MODULE ViewImage
	DEF_DLL MoveWindow(HWND,int,int,int,int,BOOL): BOOL: user32
	DIM _form, _widForm, _hwndForm

	PROCEDURE ViewImage
		_form = CREATEFORM("about:blank", "Image Viewer", TRUE, FOM_NORESIZE, 1, 1)
		_widForm = GETID(GET_FORM_WIN)
		CTRLWIN(_widForm, HIDE)
		_hwndForm = IDTOHND(_widForm)

		DEF_DLL GetWindowLongA(HWND,int): DWORD: user32
		DEF_DLL SetWindowLongA(HWND,int,DWORD): DWORD: user32
		CONST GWL_STYLE = -16
		SetWindowLongA(_hwndForm, GWL_STYLE, GetWindowLongA(_hwndForm, GWL_STYLE) AND $FF37FFFF)

		_form.document.write("<html><body style='overflow:hidden;border-style:none;margin:0px;'><img id='idimg'/></body></html>")
	FEND

	PROCEDURE Show(url, x=EMPTY, y=EMPTY)
		_form.document.all.idimg.src = url
		IF x = EMPTY THEN x = STATUS(_widForm, ST_X)
		IF y = EMPTY THEN y = STATUS(_widForm, ST_Y)
		Move(x, y)
		CTRLWIN(_widForm, SHOW)
	FEND

	PROCEDURE Move(x, y, bRepaint=TRUE)
		MoveWindow(_hwndForm, x, y, _form.document.all.idimg.width, _form.document.all.idimg.height, bRepaint)
	FEND

	PROCEDURE Hide()
		CTRLWIN(_widForm, HIDE)
	FEND

	PROCEDURE Dispose()
		_form.Quit()
	FEND
ENDMODULE

IEオブジェクトを使う

  • メリット
    • (多分IE8以降)ファイルなしに表示できる
  • デメリット
    • タイトルバー消せない
    • 枠も消せない
    • ファイル読込みができなかった(スクリプトで読み込めば出来るけど)

CreateWindowを使う

  • メリット
    • 前述のデメリットがない
  • デメリット
    • Pro版の売上げに貢献できない
    • 意味不明な呪文が必要(再描画無視なら不要)

気が向いたので、再描画無視版を書いてみた。
WindowBitmap_noRepaint.uws

OPTION EXPLICIT


IFB GET_UWSC_NAME = "WindowBitmap_noRepaint.uws" THEN

	DIM bFirst = TRUE
	WHILE !GETKEYSTATE(VK_ESC)
		IFB GETKEYSTATE(VK_SPACE) OR bFirst THEN
			DIM path = INPUT("ビットマップファイルを指定してください")
			IFB path = EMPTY THEN
				BREAK
			ELSE
				WindowBitmap.ShowFile(path)
				IF bFirst THEN CTRLWIN(WindowBitmap.WID, SHOW)
			ENDIF
			bFirst = FALSE
		ENDIF
	WEND

ENDIF


MODULE WindowBitmap
	DEF_DLL CreateWindowExA(DWORD,string,string,DWORD,int,int,int,int,DWORD,DWORD,DWORD,DWORD): DWORD: user32

	DEF_DLL GetDC(HWND): DWORD: user32
	DEF_DLL BitBlt(DWORD,int,int,int,int,DWORD,int,int,DWORD): BOOL: gdi32
	DEF_DLL ReleaseDC(HWND,DWORD): long: user32
	DEF_DLL SelectObject(DWORD,DWORD): DWORD: gdi32
	DEF_DLL DeleteDC(DWORD): BOOL: gdi32
	DEF_DLL DeleteObject(DWORD): BOOL: gdi32
	DEF_DLL InvalidateRect(HWND,DWORD,BOOL): BOOL: user32

	DEF_DLL LoadImageA(DWORD,string,DWORD,int,int,DWORD): DWORD: user32
	DEF_DLL CreateCompatibleDC(DWORD): DWORD: gdi32
	DEF_DLL CreateCompatibleBitmap(DWORD,int,int): DWORD: gdi32
	DEF_DLL MoveWindow(HWND,int,int,int,int,BOOL): BOOL: user32
	DEF_DLL GetDIBits(DWORD,DWORD,DWORD,DWORD,var BYTE,{DWORD,LONG,LONG,WORD,WORD,DWORD,DWORD,LONG,LONG,DWORD,DWORD},DWORD): int: gdi32

	PUBLIC WID = 0

	DIM _hWnd = 0


	PROCEDURE ShowFile(bmpPath, x=0, y=0, width=-1, height=-1)
		DIM hBitmap = LoadImageA(0, bmpPath, 0, 0, 0, $10)	// LR_LOADFROMFILE
		ShowHBitmap(hBitmap, x, y, width, height)
		DeleteObject(hBitmap)
	FEND
	PROCEDURE ShowHBitmap(hBmp, x=0, y=0, width=-1, height=-1)

		// ウインドウがなければ作成する
		IFB _hWnd = 0 THEN
			IFB !Create(x, y, width, height) THEN
				PRINT "ShowFile Create Error"
				EXIT
			ENDIF
			CTRLWIN(WID, SHOW)
		ENDIF

		DIM hDcP = GetDC(_hWnd)
		DIM hDcMem = CreateCompatibleDC(hDcP)
		DIM hBitOld = SelectObject(hDcMem, hBmp)

		DIM biWidth, biHeight
		IFB width = -1 OR height = -1 THEN
			DIM biSize=40,biPlanes,biBitCount,biComp,biSizeImage,biXpm,biYpm,biClrU,biClrI
			GetDIBits(hDcP, hBmp, 0, 0, NULL, biSize, biWidth, biHeight, biPlanes, biBitCount, biComp, biSizeImage, biXpm, biYpm, biClrU, biClrI, 0) // DIB_RGB_COLORS
			// ウインドウがあってサイズが異なる場合修正する
			IFB _hWnd <> 0 AND (STATUS(WID, ST_CLWIDTH) <> biWidth OR STATUS(WID, ST_CLHEIGHT) <> biHeight) THEN
				Move(STATUS(WID, ST_X), STATUS(WID, ST_Y), biWidth, biHeight)
			ENDIF
		ENDIF
		IF width = -1 THEN width = biWidth
		IF height = -1  THEN height = biHeight

		BitBlt(hDcP, 0, 0, width, height, hDcMem, 0, 0, $00CC0020)	// SRCCOPY

		SelectObject(hDcMem, hBitOld)
		DeleteDC(hDcMem)
		ReleaseDC(_hWnd, hDcP)

	FEND

	FUNCTION Create(x=0, y=0, w=100, h=100)
		RESULT = FALSE
		// ウインドウを作成する
		_hWnd = CreateWindowExA(0,"SysHeader32","ImageView",$80000000,x,y,w,h,0,0,0,0)
		IFB _hWnd THEN
			RESULT = TRUE
			WID = HNDTOID(_hWnd)
		ENDIF
	FEND

	FUNCTION Move(x, y, w=EMPTY, h=EMPTY, bRepaint=TRUE)
		IF w = EMPTY THEN w = STATUS(WID, ST_WIDTH)
		IF h = EMPTY THEN h = STATUS(WID, ST_HEIGHT)
		RESULT = MoveWindow(_hWnd, x, y, w, h, bRepaint)
	FEND

ENDMODULE

雑感

ということで、Pro版のフォーム方式だけ記載。
ま、Windowsが動作している以上、ファイル書き込みは発生しているのです。
一旦ファイルに書き込むくらい、気にしない気にしない。


透過処理については、
UWSCでウインドウスタイルを変更する - じゅんじゅんのきまぐれ
参照のこと。
SetTransparentの第三引数にカラーコードを指定すると、その色が透過色になります。


notepad等、他プロセスに描画する方法は、再描画に耐えられないのでパス。
(他プロセス方式を描画対応するくらいなら、CreateWindowだね)