-
Notifications
You must be signed in to change notification settings - Fork 165
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Windows Imaging Component を使って背景画像を読み込み、透過描画対応 #683
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -46,6 +46,8 @@ LIBS= \ | |
-limagehlp \ | ||
-lshlwapi \ | ||
-lwinmm \ | ||
-lwindowscodecs \ | ||
-lmsimg32 \ | ||
-mwindows \ | ||
$(MYLIBS) | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -45,6 +45,9 @@ | |
#include <string.h> // Apr. 03, 2003 genta | ||
#include <memory> | ||
#include <OleCtl.h> | ||
#include <wincodec.h> | ||
#pragma comment(lib, "windowscodecs.lib") | ||
#include <wrl.h> | ||
#include "doc/CEditDoc.h" | ||
#include "doc/logic/CDocLine.h" /// 2002/2/3 aroka | ||
#include "doc/layout/CLayout.h" // 2007.08.22 ryoji 追加 | ||
|
@@ -317,61 +320,70 @@ void CEditDoc::SetBackgroundImage() | |
GetInidirOrExedir( &fullPath[0], &path[0] ); | ||
path = fullPath; | ||
} | ||
const TCHAR* ext = path.GetExt(); | ||
if( 0 != auto_stricmp(ext, _T(".bmp")) ){ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. メモ: extが"bmp"と一致する場合、Bitmapを読み込んで都合よく変換する |
||
HANDLE hFile = ::CreateFile(path.c_str(), GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0); | ||
if( hFile == INVALID_HANDLE_VALUE ){ | ||
return; | ||
} | ||
DWORD fileSize = ::GetFileSize(hFile, NULL); | ||
HGLOBAL hGlobal = ::GlobalAlloc(GMEM_MOVEABLE, fileSize); | ||
if( hGlobal == NULL ){ | ||
::CloseHandle(hFile); | ||
return; | ||
} | ||
DWORD nRead; | ||
BOOL bRead = ::ReadFile(hFile, GlobalLock(hGlobal), fileSize, &nRead, NULL); | ||
::CloseHandle(hFile); | ||
hFile = NULL; | ||
if( !bRead ){ | ||
::GlobalFree(hGlobal); | ||
return; | ||
} | ||
::GlobalUnlock(hGlobal); | ||
{ | ||
IPicture* iPicture = NULL; | ||
IStream* iStream = NULL; | ||
//hGlobalの管理を移譲 | ||
if( S_OK != ::CreateStreamOnHGlobal(hGlobal, TRUE, &iStream) ){ | ||
GlobalFree(hGlobal); | ||
}else{ | ||
if( S_OK != ::OleLoadPicture(iStream, fileSize, FALSE, IID_IPicture, (void**)&iPicture) ){ | ||
}else{ | ||
HBITMAP hBitmap = NULL; | ||
short imgType = PICTYPE_NONE; | ||
if( S_OK == iPicture->get_Type(&imgType) && imgType == PICTYPE_BITMAP && | ||
S_OK == iPicture->get_Handle((OLE_HANDLE*)&hBitmap) ){ | ||
m_nBackImgWidth = m_nBackImgHeight = 1; | ||
m_hBackImg = (HBITMAP)::CopyImage(hBitmap, IMAGE_BITMAP, 0, 0, 0); | ||
} | ||
} | ||
} | ||
if( iStream ) iStream->Release(); | ||
if( iPicture ) iPicture->Release(); | ||
} | ||
}else{ | ||
m_hBackImg = (HBITMAP)::LoadImage(NULL, path.c_str(), IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. メモ: extがbmpと一致しない場合、Bitmapとして「そのまま」読み込む 背景画像に指定したbmpファイルを削除できないのはこれが原因・・・(削られてますなw |
||
} | ||
if( m_hBackImg ){ | ||
BITMAP bmp; | ||
GetObject(m_hBackImg, sizeof(BITMAP), &bmp); | ||
m_nBackImgWidth = bmp.bmWidth; | ||
m_nBackImgHeight = bmp.bmHeight; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. メモ:bitmapを読込できた場合、サイズ情報を取得している 読込できなかった場合の考慮はなし、メッセージもなし。 |
||
if( 0 == m_nBackImgWidth || 0 == m_nBackImgHeight ){ | ||
::DeleteObject(m_hBackImg); | ||
m_hBackImg = NULL; | ||
} | ||
|
||
using namespace Microsoft::WRL; | ||
ComPtr<IWICImagingFactory> pIWICFactory; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. メモ: usingに注意。ComPtrの使い方はATL/MFCのCComPtrとほぼ同じです。 |
||
HRESULT hr; | ||
hr = CoCreateInstance( | ||
CLSID_WICImagingFactory, | ||
NULL, | ||
CLSCTX_INPROC_SERVER, | ||
IID_PPV_ARGS(&pIWICFactory)); | ||
if( FAILED(hr) ) return; | ||
ComPtr<IWICBitmapDecoder> pDecoder; | ||
hr = pIWICFactory->CreateDecoderFromFilename( | ||
path.c_str(), | ||
NULL, | ||
GENERIC_READ, | ||
WICDecodeMetadataCacheOnLoad, | ||
&pDecoder); | ||
if( FAILED(hr) ) return; | ||
ComPtr<IWICBitmapFrameDecode> pFrame; | ||
hr = pDecoder->GetFrame(0, &pFrame); | ||
if( FAILED(hr) ) return; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. メモ: WICは昔windows xpに搭載されていた「イメージング」の基盤になってる技術です。パラパラ漫画のように複数画像をアニメーション表示できる画像フォーマットに対応するためWICの画像データは複数イメージ前提で構成されています。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 画像ファイルフォーマットによっては複数フレームの絵が入るのでそれに対応しているAPIですね。 WIC自体がいつから登場したのは記憶に無いですが確か Vista 以降ですね。結局芽が出なかった WinFS 以外にも色んなコンポーネントを裏では準備していたんでしょうね。 |
||
//WICPixelFormatGUID pixelFormat; | ||
//hr = pFrame->GetPixelFormat(&pixelFormat); | ||
//if( FAILED(hr) ) return; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. メモ: WICで画像のピクセル形式を確認するための標準的なコードがコメントアウトされています。 フォーマット変換するので変換前を取得してみたけど、変換前フォーマットが要らなかった、ということかと思っています。あっても邪魔にはならないからこのままでいいかな~とか。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. アルファチャンネルを含んでいない画像フォーマットな場合には 24bit DIB で済ませて、AlphaBlend による描画ではなくて従来通りの BitBlt で済ますのが良いと思いますがその判定を少ない記述で済ます方法が分からなくて諦めました。ここのコメントはその名残です。 |
||
ComPtr<IWICFormatConverter> pConverter; | ||
pIWICFactory->CreateFormatConverter(&pConverter); | ||
if( FAILED(hr) ) return; | ||
hr = pConverter->Initialize( | ||
pFrame.Get(), | ||
GUID_WICPixelFormat32bppPBGRA, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. メモ:WICのフォーマット定数はGUIDで、色々あります。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. PBGRA の P はプログレッシブではなく、premultiplied alpha を示している文字かと思います。Progressive と Djent ともまた違った関係性です。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
かなり長いこと勘違いしてました。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. なおAPI関数の 自分や arigayas さんが貼り付けたスクリーンショット(自分が貼ったのは今はもう修正済み)を見て半透過部分が正しく描画されてなくて問題に気づきました。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 見映えに関する修正は通りやすいですが、 描画のとこは最悪「あとで修正」も容易なのでスルーしてました・・・ |
||
WICBitmapDitherTypeNone, | ||
NULL, | ||
0.f, | ||
WICBitmapPaletteTypeCustom); | ||
if( FAILED(hr) ) return; | ||
UINT width, height; | ||
hr = pConverter->GetSize(&width, &height); | ||
if( FAILED(hr) ) return; | ||
BITMAPINFO bminfo = {0}; | ||
BITMAPINFOHEADER& bmih = bminfo.bmiHeader; | ||
bmih.biSize = sizeof(BITMAPINFOHEADER); | ||
bmih.biWidth = (LONG)width; | ||
bmih.biHeight = -(LONG)height; | ||
bmih.biPlanes = 1; | ||
bmih.biBitCount = 32; | ||
bmih.biCompression = BI_RGB; | ||
HDC hdcScreen = GetDC(NULL); | ||
if( !hdcScreen ) return; | ||
void *pvImageBits = NULL; | ||
m_hBackImg = CreateDIBSection(hdcScreen, &bminfo, DIB_RGB_COLORS, &pvImageBits, NULL, 0); | ||
ReleaseDC(NULL, hdcScreen); | ||
if( !m_hBackImg ) return; | ||
UINT lineStride = 4 * width; | ||
hr = pConverter->CopyPixels( | ||
NULL, | ||
lineStride, | ||
lineStride * height, | ||
(BYTE*)pvImageBits); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. メモ:変換済みビットマップからpixelデータを取り出してDIBSectionのビット領域にコピーしています。 |
||
if( FAILED(hr) ){ | ||
::DeleteObject(m_hBackImg); | ||
m_hBackImg = NULL; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. メモ:ビット領域をコピーできなくても、CreateDIBSectionで作ったビットマップは削除が必要です。 |
||
} | ||
m_nBackImgWidth = (int)width; | ||
m_nBackImgHeight = (int)height; | ||
} | ||
|
||
/* 全ビューの初期化:ファイルオープン/クローズ時等に、ビューを初期化する */ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -26,6 +26,7 @@ | |
#include "StdAfx.h" | ||
#include <vector> | ||
#include <limits.h> | ||
#pragma comment(lib, "Msimg32.lib") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. メモ:これも There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. プリコンパイル済みヘッダに変更が入るといったん全体のビルドが必要になるので抵抗感があります。 自分は何か別の cpp ファイルを1つ作って、 プロジェクトのプロパティ(Linker, Input)で指定する方法は、VS2005 とかの頃は追加すると全体のビルドが必要になってしまってうげーっと思いましたが VS2017 で試してみるとそんな事無いですね。記憶違いでしょうか…。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
「あるべき姿は あるべきを語り出すと面倒くさいので放置でもいいかな、とかも思ったり。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. #pragma というコンパイラ依存の記述に「あるべき場所」が存在するということに納得がいっていません。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. StdAfx.h の中身は「ほぼすべてのソースファイルが必要とする基礎的なヘッダファイル」だと理解しています。画像関係は違う気がします。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
たくさんのソースコードで参照されるかどうかは関係ないと思います。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
例えば、 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Stdafx.h 中に記述されているマニフェストの依存関係指定ですが、Visual Studio 2005 から使えるようになったみたいですね。 VisualStudio 2018 でMFCアプリを新規作成したところ下記の記述が Stdafx.h に入る事を確認しました。 #ifdef _UNICODE
#if defined _M_IX86
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
#elif defined _M_X64
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
#else
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
#endif
#endif なお以下がサクラエディタの Stdafx.h ファイル中の記述です。 #if defined _M_IX86
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
#elif defined _M_IA64
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"")
#elif defined _M_X64
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
#else
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
#endif Intel の Itanium プロセッサはそもそも誰も動作確認していないので記述を打ち切って良いと思います。 https://blogs.msdn.microsoft.com/oldnewthing/20070531-00/?p=26623 に書かれてましたがそもそも processorArchitecture はワイルドカード指定で良いみたいです。 #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") そして Stdafx.h ファイルでなくても問題無いので、今後 #pragma comment(linker, .... の記述が増える事を考えると将来的に Stdafx.h から別のファイルに移動しても良いかも知れないと思いました。ただ Stdafx.h ファイルをいじると全体のビルドが必要になるので、Stdafx.h ファイルに何か記述を追加する必要が生じた時についでに、でも良いと思います。全体のビルドもサクラエディタはそこまで重いとは思いませんが…。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
マニュフェスト自体が vista 以降だった気が。
これは提案すれば反対する人いないと思います。
一度どこかで話題に出た気がします。 ワイルドカードを指定した場合には、
いずれもプロジェクト設定で指定できますが、プリプロセッサで内容を変えられるのが リンカオプションは矛盾した指定をしてしまう可能性があるので多用すべきでない気がします。 |
||
#include "view/CEditView_Paint.h" | ||
#include "view/CEditView.h" | ||
#include "view/CViewFont.h" | ||
|
@@ -198,6 +199,8 @@ void CEditView::DrawBackImage(HDC hdc, RECT& rcPaint, HDC hdcBgImg) | |
#else | ||
CTypeSupport cTextType(this,COLORIDX_TEXT); | ||
COLORREF colorOld = ::SetBkColor(hdc, cTextType.GetBackColor()); | ||
MyFillRect(hdc, rcPaint); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. メモ: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. GDI 使った描画から Direct2D 使った描画に切替がぼちぼち必要ですね。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 切替というかGdi描画機構は可能な限り残したいなぁ・・・と思ってます。 テキスト描画方法の変更に着手できるのは年明け以降になる見込みですが、直接directwrite実装に移行させたい所存です。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 直接 GDI や Direct2D, DirectWrite の API を叩かないでクラスで包んでから呼び出すようにするのが良いと思いますが、空想と現実の間には距離がありますね。要求するニーズを満たすクラスの設計も実装も大変だし面倒だし。 |
||
|
||
const CTextArea& area = GetTextArea(); | ||
const CEditDoc& doc = *m_pcEditDoc; | ||
const STypeConfig& typeConfig = doc.m_cDocType.GetDocumentAttribute(); | ||
|
@@ -279,20 +282,29 @@ void CEditView::DrawBackImage(HDC hdc, RECT& rcPaint, HDC hdcBgImg) | |
CMyRect rcBltAll; | ||
rcBltAll.SetLTRB(INT_MAX, INT_MAX, -INT_MAX, -INT_MAX); | ||
CMyRect rcImagePosOrg = rcImagePos; | ||
BLENDFUNCTION bf; | ||
bf.BlendOp = AC_SRC_OVER; | ||
bf.BlendFlags = 0; | ||
bf.SourceConstantAlpha = 0xFF; | ||
bf.AlphaFormat = AC_SRC_ALPHA; | ||
for(; rcImagePos.top <= nYEnd; ){ | ||
for(; rcImagePos.left <= nXEnd; ){ | ||
CMyRect rcBlt; | ||
if( ::IntersectRect(&rcBlt, &rc, &rcImagePos) ){ | ||
::BitBlt( | ||
int width = rcBlt.right - rcBlt.left; | ||
int height = rcBlt.bottom - rcBlt.top; | ||
::AlphaBlend( | ||
hdc, | ||
rcBlt.left, | ||
rcBlt.top, | ||
rcBlt.right - rcBlt.left, | ||
rcBlt.bottom - rcBlt.top, | ||
width, | ||
height, | ||
hdcBgImg, | ||
rcBlt.left - rcImagePos.left, | ||
rcBlt.top - rcImagePos.top, | ||
SRCCOPY | ||
width, | ||
height, | ||
bf | ||
); | ||
rcBltAll.left = t_min(rcBltAll.left, rcBlt.left); | ||
rcBltAll.top = t_min(rcBltAll.top, rcBlt.top); | ||
|
@@ -336,8 +348,6 @@ void CEditView::DrawBackImage(HDC hdc, RECT& rcPaint, HDC hdcBgImg) | |
if( y3 < y4 ){ | ||
rcFill.SetLTRB(x1,y3, x4,y4); MyFillRect(hdc, rcFill); | ||
} | ||
}else{ | ||
MyFillRect(hdc, rc); | ||
} | ||
::SetBkColor(hdc, colorOld); | ||
#endif | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
レビューコメントではないですが
この3行は
StdAfx.h
に移動したいな、って思ってます。There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sakura/sakura_core/doc/CEditDoc.cpp
Lines 45 to 46 in 070d76a
γ  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ヽ
|彡(゚)(゚) 彡(゚)(゚) あれ?ワイらは? |
乂_______________ノ
sakura/sakura_core/doc/CEditDoc.cpp
Line 47 in 070d76a
γ  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ヽ
| 彡(゚)(゚) ここにいても いいの? |
乂______________ノ
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
「移動」じゃなくてもいいっすよ。
まぁ
#include <string.h>
は削りたいです。