アルファブレンド・プログラミングチップス
プログラミングチップス
  • BLOG
  • TIPS
  • LINK
  • CONTACT
  • HOME
  • SITEMAP
  • ALPHABREND
TIPS/VisualC++/フローティング中のツールバーを斜めにサイズ変更できるようにする
[ リロード ]   [ ソース ]  [ トップ | 一覧 | 単語検索 | 最新 | バックアップ | ヘルプ ]

トップ > TIPS > VisualC++ > フローティング中のツールバーを斜めにサイズ変更できるようにする
[ ページコメント(0) ] [ トラックバック(0) ]
Counter: 1317, today: 2, yesterday: 2
縦書きコンボボックス Prev Next ツールバーに256色(8bit)の画像を使用する

フローティング中のツールバーを斜めにサイズ変更できるようにする

ツールバーなどのコントロールバーはフローティング中、
通常縦横にしかサイズ変更ができません。
カーソルをあわせても斜めのカーソルがでません。
まずはそれを修正します。

コントロールバーがフローティングを実現する時には、
CMiniDockFrameWndというクラスのウィンドウの
子(孫)ウィンドウになっています。
このCMiniDockFrameWndがカーソルを制御しています。

下記のCMiniDockFrameWndの派生元クラス
CMiniFrameWndのOnNcHitTestの部分で
縦横にしかカーソルがでないようにしています。

	if (dwStyle & MFS_4THICKFRAME)
	{
		switch (nHit)
		{
		case HTTOPLEFT:
			return point.y < rectWindow.top ? HTTOP : HTLEFT;
		case HTTOPRIGHT:
			return point.y < rectWindow.top ? HTTOP : HTRIGHT;
		case HTBOTTOMLEFT:
			return point.y > rectWindow.bottom ? HTBOTTOM : HTLEFT;
		case HTGROWBOX:
		case HTBOTTOMRIGHT:
			return point.y > rectWindow.bottom ? HTBOTTOM : HTRIGHT;
		}
	}

ですので、CMiniDockFrameWndのウィンドウスタイルから
MFS_4THICKFRAMEを消してしまいましょう。
CControlBarから継承したクラスCMyControlBarに
以下の二つの関数を追加すればOKです。

CMiniDockFrameWnd* CMyControlBar::GetMiniDockFrameWnd()
{
	CWnd				*pWnd;


	if( m_hWnd )
	{
		if( pWnd = GetParent() )
		{
			if( pWnd = pWnd->GetParent() )
			{
				if( pWnd->IsKindOf( RUNTIME_CLASS( CMiniDockFrameWnd ) ) )
				{
					return (CMiniDockFrameWnd*)pWnd;
				}
			}
		}
	}

	return 0;
}

void CMyControlBar::OnSize(UINT nType, int cx, int cy) 
{
	CControlBar::OnSize(nType, cx, cy);

	if( GetMiniDockFrameWnd() )
	{
		GetMiniDockFrameWnd()->ModifyStyle( MFS_4THICKFRAME, 0 );
	}
}

これで斜めにもカーソルがでるようになります。
…が、まだサイズ変更はできません。
この原因を確かめるべく、
CMiniDockFrameWndのOnNcLButtonDownから追っていくと、

pBar->m_pDockContext->StartResize(nHitTest, point);
↓
Stretch(pt);

という関数のこの部分

	if (m_nHitTest == HTLEFT || m_nHitTest == HTRIGHT)
	{
		if (m_nHitTest == HTLEFT)
			m_rectRequestedSize.left += ptOffset.x;
		else
			m_rectRequestedSize.right += ptOffset.x;
		nLength = m_rectRequestedSize.Width();
	}
	else
	{
		dwMode |= LM_LENGTHY;
		if (m_nHitTest == HTTOP)
			m_rectRequestedSize.top += ptOffset.y;
		else
			m_rectRequestedSize.bottom += ptOffset.y;
		nLength = m_rectRequestedSize.Height();
	}

このように上下左右しか扱っていません。
なので、HitTestが斜めの時は斜めに操作できるように
処理を奪い取りましょう。

アプリケーションクラスに以下の処理を追加してください。
長いですが。

BOOL CMyApp::PreTranslateMessage(MSG* pMsg)
{
	CMiniDockFrameWnd	*pMiniWnd = 0;
	BOOL				bMiniWnd;
	CPoint				pos;


	switch( pMsg->message )
	{
	case WM_NCLBUTTONDOWN:
		pMiniWnd	= m_myBar.GetMiniDockFrameWnd();
		if( pMiniWnd && pMiniWnd->m_hWnd == pMsg->hwnd )
		{
			switch( pMsg->wParam )
			{
			case HTTOPLEFT:
			case HTTOPRIGHT:
			case HTBOTTOMLEFT:
			case HTBOTTOMRIGHT:
				pos.x	= (LONG)pMsg->lParam & 0xFFFF;
				pos.y	= (LONG)pMsg->lParam >> 16;
				StretchWnd( pMiniWnd, (int)pMsg->wParam, pos );
				return TRUE;
			}
		}
		break;
	}

	return CWinApp::PreTranslateMessage(pMsg);
}

#define m_rectRequestedSize     m_rectDragHorz
#define m_rectActualSize        m_rectDragVert
#define m_rectActualFrameSize   m_rectFrameDragHorz
#define m_rectFrameBorders      m_rectFrameDragVert
struct AUX_DATA
{
	// system metrics
	int cxVScroll, cyHScroll;
	int cxIcon, cyIcon;

	int cxBorder2, cyBorder2;

	// device metrics for screen
	int cxPixelsPerInch, cyPixelsPerInch;

	// convenient system color
	HBRUSH hbrWindowFrame;
	HBRUSH hbrBtnFace;

	// color values of system colors used for CToolBar
	COLORREF clrBtnFace, clrBtnShadow, clrBtnHilite;
	COLORREF clrBtnText, clrWindowFrame;

	// standard cursors
	HCURSOR hcurWait;
	HCURSOR hcurArrow;
	HCURSOR hcurHelp;       // cursor used in Shift+F1 help

	// special GDI objects allocated on demand
	HFONT   hStatusFont;
	HFONT   hToolTipsFont;
	HBITMAP hbmMenuDot;

	// other system information
	BOOL    bWin95;         // TRUE if Windows 95 (not NT)

// Implementation
	AUX_DATA();
	~AUX_DATA();
	void UpdateSysColors();
	void UpdateSysMetrics();
};
extern AUX_DATA afxData;

void CMyApp::StretchWnd( CMiniDockFrameWnd *pMiniWnd, int nHitTest, CPoint pt )
{
	int nPos = 1;
	CControlBar* pBar = NULL;
	while(pBar == NULL && nPos < pMiniWnd->m_wndDockBar.m_arrBars.GetSize())
	{
		CControlBar* pResult = (CControlBar*)pMiniWnd->m_wndDockBar.m_arrBars[nPos];
		if (DWORD_PTR(pResult) <= 0xffff)
			pBar	= NULL;
		else
			pBar	= pResult;
	}

	ASSERT(pBar != NULL);
	ASSERT_KINDOF(CControlBar, pBar);
	ASSERT(pBar->m_pDockContext != NULL);

	// CBRS_SIZE_DYNAMIC toolbars cannot have the CBRS_FLOAT_MULTI style
	ASSERT((pMiniWnd->m_wndDockBar.m_dwStyle & CBRS_FLOAT_MULTI) == 0);
	ASSERT_VALID(pBar->m_pDockContext->m_pBar);
	ASSERT(pBar->m_pDockContext->m_pBar->m_dwStyle & CBRS_SIZE_DYNAMIC);
	pBar->m_pDockContext->m_bDragging = FALSE;

	pBar->m_pDockContext->InitLoop();

	// GetWindowRect returns screen coordinates(not mirrored)
	// So if the desktop is mirrored then turn off mirroring
	// for the desktop dc so that we draw correct focus rect 

	if (pBar->m_pDockContext->m_pDC->GetLayout() & LAYOUT_RTL)
		pBar->m_pDockContext->m_pDC->SetLayout(LAYOUT_LTR);

	// get true bar size (including borders)
	CRect rect;
	pBar->m_pDockContext->m_pBar->GetWindowRect(rect);
	pBar->m_pDockContext->m_ptLast = pt;
	pBar->m_pDockContext->m_nHitTest = nHitTest;

	CSize size = pBar->m_pDockContext->m_pBar->CalcDynamicLayout(0, LM_HORZ | LM_MRUWIDTH);
	pBar->m_pDockContext->m_rectRequestedSize = CRect(rect.TopLeft(), size);
	pBar->m_pDockContext->m_rectActualSize = CRect(rect.TopLeft(), size);
	pBar->m_pDockContext->m_rectActualFrameSize = CRect(rect.TopLeft(), size);

	// calculate frame rectangle
	CMiniFrameWnd::CalcBorders(&pBar->m_pDockContext->m_rectActualFrameSize);
	pBar->m_pDockContext->m_rectActualFrameSize.InflateRect(-afxData.cxBorder2, -afxData.cyBorder2);

	pBar->m_pDockContext->m_rectFrameBorders = CRect(CPoint(0,0),
		pBar->m_pDockContext->m_rectActualFrameSize.Size() - pBar->m_pDockContext->m_rectActualSize.Size());

	// initialize tracking state and enter tracking loop
	pBar->m_pDockContext->m_dwOverDockStyle = 0;
	StretchMiniWnd( pBar, pt );
	TrackMiniWnd( pBar );

	return;
}

void CMyApp::StretchMiniWnd( CControlBar* pBar, CPoint pt )
{
	CPoint ptOffset = pt - pBar->m_pDockContext->m_ptLast;

	// offset all drag rects to new position
	int nLength = 0;
	DWORD dwMode = LM_HORZ;

	switch( pBar->m_pDockContext->m_nHitTest )
	{
	case HTTOPLEFT:
		pBar->m_pDockContext->m_rectRequestedSize.left	+= ptOffset.x;
		pBar->m_pDockContext->m_rectRequestedSize.top	+= ptOffset.y;
		break;
	case HTTOPRIGHT:
		pBar->m_pDockContext->m_rectRequestedSize.top	+= ptOffset.y;
		pBar->m_pDockContext->m_rectRequestedSize.right	+= ptOffset.x;
		break;
	case HTBOTTOMLEFT:
		pBar->m_pDockContext->m_rectRequestedSize.left	+= ptOffset.x;
		pBar->m_pDockContext->m_rectRequestedSize.bottom	+= ptOffset.y;
		break;
	case HTBOTTOMRIGHT:
		pBar->m_pDockContext->m_rectRequestedSize.right	+= ptOffset.x;
		pBar->m_pDockContext->m_rectRequestedSize.bottom	+= ptOffset.y;
		break;
	}

	CSize	size;
	nLength = pBar->m_pDockContext->m_rectRequestedSize.Width();
	nLength = (nLength >= 0) ? nLength : 0;
	size = pBar->m_pDockContext->m_pBar->CalcDynamicLayout(nLength, dwMode);
	dwMode |= LM_LENGTHY;
	nLength = pBar->m_pDockContext->m_rectRequestedSize.Height();
	nLength = (nLength >= 0) ? nLength : 0;
	size = pBar->m_pDockContext->m_pBar->CalcDynamicLayout(nLength, dwMode);

	CRect rectDesk;
	HWND hWndDesk = ::GetDesktopWindow();
	::GetWindowRect(hWndDesk, &rectDesk);
	CRect rectTemp = pBar->m_pDockContext->m_rectActualFrameSize;

	CRect rect;
	switch( pBar->m_pDockContext->m_nHitTest )
	{
	case HTTOPLEFT:
		rectTemp.left = rectTemp.right - (size.cx + pBar->m_pDockContext->m_rectFrameBorders.Width());
		rectTemp.top = rectTemp.bottom - (size.cy + pBar->m_pDockContext->m_rectFrameBorders.Height());
		if (rect.IntersectRect(rectDesk, rectTemp))
		{
			pBar->m_pDockContext->m_rectActualSize.left = pBar->m_pDockContext->m_rectActualSize.right - size.cx;
			pBar->m_pDockContext->m_rectActualSize.top = pBar->m_pDockContext->m_rectActualSize.bottom - size.cy;
			pBar->m_pDockContext->m_rectActualFrameSize.left = rectTemp.left;
			pBar->m_pDockContext->m_rectActualFrameSize.top = rectTemp.top;
		}
		break;
	case HTTOPRIGHT:
		rectTemp.right = rectTemp.left + (size.cx + pBar->m_pDockContext->m_rectFrameBorders.Width());
		rectTemp.top = rectTemp.bottom - (size.cy + pBar->m_pDockContext->m_rectFrameBorders.Height());
		if (rect.IntersectRect(rectDesk, rectTemp))
		{
			pBar->m_pDockContext->m_rectActualSize.top = pBar->m_pDockContext->m_rectActualSize.bottom - size.cy;
			pBar->m_pDockContext->m_rectActualSize.right = pBar->m_pDockContext->m_rectActualSize.left + size.cx;
			pBar->m_pDockContext->m_rectActualFrameSize.top = rectTemp.top;
			pBar->m_pDockContext->m_rectActualFrameSize.right = rectTemp.right;
		}
		break;
	case HTBOTTOMLEFT:
		rectTemp.left = rectTemp.right - (size.cx + pBar->m_pDockContext->m_rectFrameBorders.Width());
		rectTemp.bottom = rectTemp.top + (size.cy + pBar->m_pDockContext->m_rectFrameBorders.Height());
		if (rect.IntersectRect(rectDesk, rectTemp))
		{
			pBar->m_pDockContext->m_rectActualSize.left = pBar->m_pDockContext->m_rectActualSize.right - size.cx;
			pBar->m_pDockContext->m_rectActualSize.bottom = pBar->m_pDockContext->m_rectActualSize.top + size.cy;
			pBar->m_pDockContext->m_rectActualFrameSize.left = rectTemp.left;
			pBar->m_pDockContext->m_rectActualFrameSize.bottom = rectTemp.bottom;
		}
		break;
	case HTBOTTOMRIGHT:
		rectTemp.right = rectTemp.left + (size.cx + pBar->m_pDockContext->m_rectFrameBorders.Width());
		rectTemp.bottom = rectTemp.top + (size.cy + pBar->m_pDockContext->m_rectFrameBorders.Height());
		if (rect.IntersectRect(rectDesk, rectTemp))
		{
			pBar->m_pDockContext->m_rectActualSize.right = pBar->m_pDockContext->m_rectActualSize.left + size.cx;
			pBar->m_pDockContext->m_rectActualSize.bottom = pBar->m_pDockContext->m_rectActualSize.top + size.cy;
			pBar->m_pDockContext->m_rectActualFrameSize.right = rectTemp.right;
			pBar->m_pDockContext->m_rectActualFrameSize.bottom = rectTemp.bottom;
		}
		break;
	}
	
	pBar->m_pDockContext->m_ptLast = pt;

	// update feedback
	pBar->m_pDockContext->DrawFocusRect();

}

BOOL CMyApp::TrackMiniWnd( CControlBar *pBar )
{
	// don't handle if capture already set
	if (::GetCapture() != NULL)
		return FALSE;

	// set capture to the window which received this message
	pBar->m_pDockContext->m_pBar->SetCapture();
	ASSERT(pBar->m_pDockContext->m_pBar == CWnd::GetCapture());

	// get messages until capture lost or cancelled/accepted
	while (CWnd::GetCapture() == pBar->m_pDockContext->m_pBar)
	{
		MSG msg;
		if (!::GetMessage(&msg, NULL, 0, 0))
		{
			AfxPostQuitMessage((int)msg.wParam);
			break;
		}

		switch (msg.message)
		{
		case WM_LBUTTONUP:
			if (pBar->m_pDockContext->m_bDragging)
				pBar->m_pDockContext->EndDrag();
			else
				pBar->m_pDockContext->EndResize();
			return TRUE;
		case WM_MOUSEMOVE:
			if (pBar->m_pDockContext->m_bDragging)
				pBar->m_pDockContext->Move(msg.pt);
			else
				StretchMiniWnd( pBar, msg.pt);
			break;
		case WM_KEYUP:
			if (pBar->m_pDockContext->m_bDragging)
				pBar->m_pDockContext->OnKey((int)msg.wParam, FALSE);
			break;
		case WM_KEYDOWN:
			if (pBar->m_pDockContext->m_bDragging)
				pBar->m_pDockContext->OnKey((int)msg.wParam, TRUE);
			if (msg.wParam == VK_ESCAPE)
			{
				pBar->m_pDockContext->CancelLoop();
				return FALSE;
			}
			break;
		case WM_RBUTTONDOWN:
			pBar->m_pDockContext->CancelLoop();
			return FALSE;

		// just dispatch rest of the messages
		default:
			DispatchMessage(&msg);
			break;
		}
	}

	pBar->m_pDockContext->CancelLoop();

	return FALSE;
}

ヘッダにもちゃんと上記で作成した関数の定義を
書いておいてください。
長いですがこれで完成です。

時間と機能があまりにも割に合わない作業でした…。

付箋機能(wema) メニュー 
付箋機能 [新規] [ごみ箱] [透明] [更新] [リスト] [ヘルプ]  付箋検索: 自動更新:
付箋の編集
文字色: 背景色:
お名前:  線接続id:

[ごみ箱] [透明] [リスト] [ヘルプ]  付箋検索:

ページコメント
 
投稿された内容の著作権はコメントの投稿者に帰属します。

リロード   差分 ソース ファイル添付 添付ファイル一覧   Wikiトップ 一覧 検索 最終更新 バックアップ   ヘルプ   最終更新のRSS
ページ名:TIPS/VisualC++/フローティング中のツールバーを斜めにサイズ変更できるようにする
ページ作成:dala - 2006/05/28 23:10:17 JST(907d)
最終更新:dala - 2006/05/28 23:10:17 JST(907d)
編集可:dala
リンクページ:TIPS(11h) VisualC++(907d)
Modified by dala

"PukiWikiMod" 1.5.1 Copyright © 2003-2005 ishii & nao-pon. License is GNU/GPL.
Based on "PukiWiki" by PukiWiki Developers Team
Powered by PHP 5.2.6

HTML convert time to 0.443 sec.
Go Page Top
メインメニュー
ホーム プログラミングチップス 最新ページ一覧 ページ一覧 日記 掲示板 ダウンロード FAQ サイトマップ リンク集 お問い合わせ
WordPress カテゴリ一覧
  • Akelos
  • CakePHP
  • Flex
  • ちいたん
  • 日記
TIPS

  • CakePHP
  • CentOS
  • Flex
  • PHP
  • VisualC++
日記カレンダー
2008年 11月
日 月 火 水 木 金 土
« 9月    
 1
2345678
9101112131415
16171819202122
23242526272829
30  
最新チップス
2008-11-21
  • ヘルプ
2008-11-20
  • TIPS
2008-10-14
  • TIPS/VisualC++/縦書きエディットコントロール
2008-6-9
  • TIPS/Flex
2008-5-24
  • TIPS/CakePHP/複数形
2008-4-15
  • TIPS/PHP
2008-3-21
  • TIPS/CakePHP/scripts_for_layoutとは?
2008-3-10
  • TIPS/CakePHP
2008-3-6
  • TIPS/CakePHP/cronを使う
  • TIPS/Flex/サウンドをループ
日記最近の投稿
  • 2008-9-9
    • MySQL文字列の数値変換
  • 2008-8-28
    • XOOPSの外部利用
  • 2008-7-17
    • asp.netのタスク
  • 2008-5-15
    • 最近
  • 2008-4-24
    • オリジナルのView
  • 2008-4-1
    • Yahooが!
    • mashupedia閉鎖
  • 2008-3-31
    • ヒゲシミュレータ
  • 2008-3-28
    • Modelの追加方法
  • 2008-3-26
    • scripts_for_layout続き
日記月別過去ログ
  • 2008年 9月
  • 2008年 8月
  • 2008年 7月
  • 2008年 5月
  • 2008年 4月
  • 2008年 3月
  • 2008年 2月
  • 2007年 12月
  • 2007年 11月
  • 2007年 10月
  • 2007年 9月
  • 2007年 8月
  • 2007年 7月
  • 2007年 6月
  • 2007年 5月
  • 2007年 4月
  • 2007年 3月
  • 2007年 1月
  • 2006年 12月
  • 2006年 11月
  • 2006年 10月
  • 2006年 9月
  • 2006年 8月
  • 2006年 7月
  • 2006年 6月
  • 2006年 5月
日記検索
ログイン
ユーザ名:

パスワード:


パスワード紛失

新規登録
Powered by XOOPS Cube 2.0 © 2005-2006 The XOOPS Project theme design by BCOOL