MSFlexGrid上に描画 – プログラミング – Home

通知
すべてクリア

[解決済] MSFlexGrid上に描画


たいちう
 たいちう
(@たいちう)
ゲスト
結合: 23年前
投稿: 662
Topic starter  

たいちうです。また質問させてください。

Win2000 VC++6.0 SP5 MFC SDI で開発しています。

MSFlexGridを使って横向きの棒グラフのようなものを作成したいのですが、
どのような方法が良いのでしょうか?

まず、MSFlexGrid のセルにビットマップを貼り付ける方法ですが、
これではセルをまたがった図形を表示できません。
棒グラフ程度なら、矩形を分割して各セルに貼り付けられますが、
より複雑な図形の描画・消去が大変そうです。

次に、CStaticをMSFlexGridに重ねて描画しようかとも思ったのですが、
図形の更新のタイミングがつかめません。
グリッドの作成時やスクロールなどでは、CViewのPreTranslateMessageで、
WM_PAINTを捕らえられませんでした。

MSFlexGridを使わなくても構いません。
どなたか楽な方法を教えていただけないでしょうか?
このままでは、ビットマップを分割するか、スクロールするグリッドを
1から作るかの、2つの手段を検討することになりそうです。


引用未解決
トピックタグ
汎
 汎
(@汎)
ゲスト
結合: 22年前
投稿: 43
 

楽をするためにFlexGridを考えたのでしょうか?

CViewでの図形の描画は入門書にたくさん書いてありますので、こちらを勉強したほうがよいの
と思います

CViewでの描画はOnDrawをオーバライドします。
WM_PAINTはメッセージマップで受け取ります。

チュートリアルをきちんと勉強するほうが近道と感じます。


返信引用
たいちう
 たいちう
(@たいちう)
ゲスト
結合: 23年前
投稿: 662
Topic starter  

汎さま
回答有難うございます。
ですが、私のしたい事がうまく伝えられなかったようです。

> 楽をするためにFlexGridを考えたのでしょうか?

そうです。グリッドを表示させたり、スクロールさせたりを自分でコーディングするのが
面倒だった為、MSFlexGridの上にグラフを描画させようとしました。
ちなみにMSFlexGridはCViewの上に動的に作成しています。

コントロールの上に描画をさせたい為、CView::OnDrawで描いてはグラフの上に
MSFlexGridを上書きされてしまいます。CButtonの上に書くような場合には、CButtonを
継承させたクラスのPreTranslateMessageでWM_PAINTを捕まえる事が出来たのですが、
MSFlexGridでは、これを継承させたクラスでも、貼り付けたCViewでもWM_PAINTを
捕まえる事が出来ませんでした。少なくともこの方法ではActiveXの場合、
出来ないんだと思います。

その後も色々試しましたが、MSFlexGridをサブクラス化して、スクロールの場合も含めて
WM_PAINTを拾う事が出来ました。MFCとSDKの混じったコードになりましたが、
なんとかなりそうです。

実際に描画してスクロールにも成功したら、また報告させてもらいます。


返信引用
たいちう
 たいちう
(@たいちう)
ゲスト
結合: 23年前
投稿: 662
Topic starter  

なんとか解決しました。
わざわざ載せるまでもないかもしれませんが、
CViewにMSFlexGridを表示させる方法と、サブクラス化する方法を書いておきます。

WNDPROC OldProc;
void *pGrid;

LRESULT CALLBACK NewProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
LRESULT ret = OldProc(hwnd, message, wParam, lParam);
if (message == WM_PAINT)
((CMyView*)pGrid)->DrawGraph();
return ret;
}

void CMyView::OnInitialUpdate()
{
CView::OnInitialUpdate();
m_grid.Create(grid, WS_CHILD | WS_VISIBLE,
CRect(0, 0, 0, 0), this, IDC_GRID_GANTT);
OldProc = (WNDPROC)::SetWindowLong(m_grid.m_hWnd, GWL_WNDPROC,
(LONG)NewProc);
pGrid = this;
}

void CMyView::DrawGraph()
{
// ここに描画
}

この他、CMyView::OnSize()も処理しています。

結局、スクロールに合わせた描画をする必要があったので、MSFlexGridを使う
メリットは小さかったかもしれません。


返信引用
汎
 汎
(@汎)
ゲスト
結合: 22年前
投稿: 43
 

返事がおくれて申し訳ありません。
解決されてなによりです。

一般にグリッドコントロールはこのコントロールの機能を使うために使用します。
今回はグリッドコントロールの機能は使わないように受け取りましたので、
それならViewに直接描画するなり
Viewの上に子ウィンドウを生成して描画すなりするほうが
簡単だと思ったまででした。

ちなみにMFCのサブクラス化は
CWnd::SubclassWindow(); 関数
サブクラス化の解除は
CWnd::UnsubclassWindow(); 関数を使用します。


返信引用
たいちう
 たいちう
(@たいちう)
ゲスト
結合: 23年前
投稿: 662
Topic starter  

汎さま

> ちなみにMFCのサブクラス化は
> CWnd::SubclassWindow(); 関数
> サブクラス化の解除は
> CWnd::UnsubclassWindow(); 関数を使用します。

この方法も試してみましたが、ActiveXコントロールの場合にはできないようです。
サブクラス化しようとすると、MFC内部のASSERTに引っかかります。

BOOL CWnd::Attach(HWND hWndNew)
{
ASSERT(m_hWnd == NULL); // only attach once, detach on destroy
ASSERT(FromHandlePermanent(hWndNew) == NULL);
...
}

ここの、FromHandle...がNULLになってくれません。
一般のコントロールの場合では成功しましたので、手順は正しいと思うのですが、
この辺りは私の理解を超えているため、諦めざるを得ませんでした。

> 一般にグリッドコントロールはこのコントロールの機能を使うために使用します。
> 今回はグリッドコントロールの機能は使わないように受け取りましたので、
> それならViewに直接描画するなり
> Viewの上に子ウィンドウを生成して描画すなりするほうが
> 簡単だと思ったまででした。

部分的にはグリッドの機能も使います。
ですが、グラフ描画の他にもMSFlexGridがサポートしていない機能を色々実装
しなければなりませんので、「Viewの上に子ウィンドウを生成して描画」の方が
良いのかもしれません。
まあ、しばらくはこのまま作り続けてみます。ありがとうございました。


返信引用
汎
 汎
(@汎)
ゲスト
結合: 22年前
投稿: 43
 

なるほど そういった動作があったのですね

別の意味で興味深かったのでソースを組んで確認してみました。

ラッパ関数でそのまま処理するにはCreate関数を以下のように、

BOOL CMSFlexGrid::Create(LPCTSTR lpszWindowName, DWORD dwStyle, const RECT&
rect, CWnd* pParentWnd,
UINT nID, CFile* pPersist, BOOL bStorage,
BSTR bstrLicKey)
{
BOOL bRtn = CreateControl(GetClsid(), lpszWindowName, dwStyle, rect,
pParentWnd, nID, pPersist, bStorage, bstrLicKey);
m_pOldProc = (WNDPROC)GetWindowLong(GetSafeHwnd(),GWL_WNDPROC) ;
m_hWnd = Detach() ;
SubclassWindow(m_hWnd);
return bRtn ;
}

一旦ハンドルをデタッチしてからSubclassWindowを発行すれば
メッセージマップが使用できるようになります。
あとはたいちうさんと同じで

void CMSFlexGrid::OnPaint()
{
  m_pOldProc(m_hWnd, WM_PAINT, 0, 0) ;

  描画処理
}

ですね。

ただ、これでアクティブコントロールがほんとに正しく動作するかは
確認していません。

「ActiveX コントロールってこんなふうに使うもの?」という気持ちもあります。
これだけ苦労するなら自分でグリッドコントロールを作るなり
VS-FlexGridを使うほうが楽ではないでしょうか?

よけいな一言が多いので気分を害されていたら失礼しました。


返信引用
たいちう
 たいちう
(@たいちう)
ゲスト
結合: 23年前
投稿: 662
Topic starter  

汎さま

> ラッパ関数でそのまま処理するにはCreate関数を以下のように、
...
...

少し試しましたが、同じASSERTIONが出てしまいます。
いずれまた挑戦して見ます。

> 「ActiveX コントロールってこんなふうに使うもの?」という気持ちもあります。
> これだけ苦労するなら自分でグリッドコントロールを作るなり
> VS-FlexGridを使うほうが楽ではないでしょうか?

そうですね。貼り付けただけで使いたいのが本音です。
スクロール時のグラフの座標計算なども面倒だったので、
グリッドごと作るのも変わらないかもしれません。
今回だいぶ苦労した分、勉強になりました。

> よけいな一言が多いので気分を害されていたら失礼しました。

いえいえ。ありがとうございました。


返信引用

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました