スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

CakePHPのconditionsでSubqueryの結果をINで使う

CakePHPのconditionsは=>をいれないとそのままSQLのWhere句にわたるみたいですね。
そこで、
$this->ModelXX->find('all', array('conditions' => array(ModelXX.YY IN (SELECT YY FROM ZZ WHERE xxxx)'));
のようなことをかくと
ModelXX.YY IN (SELECT YY FROM ZZ WHERE xxxx)
がそのままWHERE句に入ってくれるみたいですね。
スポンサーサイト

CMFCToolBarにComboBoxを置く方法(続き2)

作成したCMFCToolBar上のComboBoxに現在の選択行を表示しようとして

iIndex = m_wndToolBar.CommandToIndex(ID_EDIT_FIND_COMBO, 0);
CMFCToolBarComboBoxButton* btn = (CMFCToolBarComboBoxButton*)m_wndToolBar.GetButton(iIndex);
btn->SelectItem(selectindex);
のようにしたのは、いいのですが、これが動作するComboBoxと動作しない(SelectItemに反応しない)ComboBoxがあってはまりました。

それで
CMFCToolBarComboBoxButton* btn = (CMFCToolBarComboBoxButton*)m_wndToolBar.GetButton(iIndex);
で取得されるbtnのデータ型をみるとCMFCToolBarComboBoxButtonではなくて、CMFCToolBarButtonになっているんですよね。
OnResetToolbarで最初に作ったときは、ちゃんとCMFCToolBarComboBoxButtonが取れていたので、どこかですりかわってしまったんだろうと思っていました。
MFCのソースを追っているとCMFCToolBarのm_Buttonsがいつのまにか増えていてこれが悪さしているのだろうと思ってどこで増えているのは調べようとしたのですがわかりませんでした。。。
ただどうもMAINFRAMEのCMFCToolbarはMFCが勝手に増やしていてそれはあまり問題になってないような感じです。
カスタマイズのツールバーのリセットを行った直後だけ、ちゃんとComboBoxが動作するのですが、それもさらに謎です。

それでいろいろしらべてみてやっと原因がわかりました。
最初にOnResetToolBarで
CMFCToolBarComboBoxButtonbtnCombo(ID_EDIT_FIND_COMBO, GetCmdMgr()->GetCmdImage(ID_EDIT_FIND), CBS_DROPDOWNLIST | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL);
m_wndToolBar.ReplaceButton(ID_EDIT_FIND, btnCombo);
のようにしてComboBoxを作成するのですが、
このときの、ID_EDIT_FIND_COMBOとID_EDIT_FINDのIDの値が違っていないとこのようなことが起こるみたいです。
これを実行した直後は)m_wndToolBar.GetButton(iIndex)も正しい結果が得られていたのですが、MFCが勝手にボタンを追加していくうちに追加前のID_EDIT_FINDのIDの空のボタンの場所がなぜか復活しててそれが返ってくるようでした。
なんかトラぶったときに非常にわかりにくいですね。。
先が思いやられます。。


CMFCToolBarにComboBoxを置く方法(続き)

前回のCMFCToolBarにComboBoxを置く方法についてですが、せっかくComboBoxをおいてデータを入れて、
そのComboBoxのポインタに SetCurSel()を行っても、ツールバー上にはなにも表示されないままになっています。
どうやら、CMFCToolBarにComboBoxをおいた場合は、そのComboBoxを直接触るのではなく、
CMFCToolBarComboBoxButtonを介してComboBoxを触るのが流儀のようです。

具体的にはCMFCToolBarからCMFCToolBarComboBoxButtonは
iIndex = m_wndToolBar.CommandToIndex(ID_EDIT_FIND_COMBO, 0);
CMFCToolBarComboBoxButton* btn = (CMFCToolBarComboBoxButton*)m_wndToolBar.GetButton(iIndex);
のようにボタンのIDから取得できるので、そのCMFCToolBarComboBoxButtonに対して
btn->SelectItem(selectindex);
のようにする必要があるということみたいです。

CMFCToolBarにComboBoxを置く方法

CMFCToolBarにComboBoxを置く方法についてですが、よく使われることなのに意外とネットに
サンプル等がのっていません。
そこで調べてみたのでその結果を途中経過として書いておきます。
旧来のCToolBarにComboBoxをおく場合は、CToolBarのSetButtonInfo()でComboBoxを入れる場所を
セパレータとして幅を設定して、その上にCreateでComboBoxを作成するという方法でできました。
しかしCMFCToolBarでは位置がうまく設定できませんでした。

CMFCToolBarの場合ではまず、
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
で普通に
!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);
!m_wndToolBar.LoadToolBar( IDR_MAINFRAME);
のようにCMFCToolBarを作っります。
ただしComboBox用に該当する部分に場所をあけて、ID_EDIT_FINDのようなIDをつけておきます。
また作成するComboBox用にID_EDIT_FIND_COMBO等とResouceのStringにIDを作成しておきます。
その後
AFX_WM_RESETTOOLBARというメッセージをCMainFrameで受け取ってその中で設定します。
AFX_WM_RESETTOOLBARのメッセージはクラスウィザードではでてこなかったので手動で

BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWndEx)
ON_REGISTERED_MESSAGE(AFX_WM_RESETTOOLBAR, OnResetToolbar)
END_MESSAGE_MAP()

LRESULT CMainFrame::OnResetToolbar(WPARAM wp, LPARAM lp)
{
}
を作ります。
この中で
wpがツールバーのIDになるので、この場合は
if (wp == IDR_MAINFRAME)
のときに設定することになります。
その設定はもっとも簡単には

CMFCToolBarComboBoxButtonbtnCombo(ID_EDIT_FIND_COMBO, GetCmdMgr()->GetCmdImage(ID_EDIT_FIND), CBS_DROPDOWNLIST | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL);
   m_wndToolBar.ReplaceButton(ID_EDIT_FIND, btnCombo);
これだけで、自動的にComboBoxを作成してくれます。
ただしID_EDIT_FIND_COMBOのOnCommandUIを処理しないと、Disableになったままです。
またレジストリをいったんきれいにしないと最初に変な場所に出たりします。。。

ただ、これだけでは作成したComboBoxが空っぽだったり、制御しにくいので
CMFCToolBarComboBoxButtonbtnComboを継承してクラスを作成し、CreateCombo()をオーバーライドすれば
作成するComboBoxを制御できます。

class CFindComboButton : public CMFCToolBarComboBoxButton {
DECLARE_SERIAL(CFindComboButton)
public:
CFindComboButton() :CMFCToolBarComboBoxButton() {
}
CFindComboButton(UINT uiID, int iImage, DWORD dwStyle = CBS_DROPDOWNLIST, int iWidth = 0) :CMFCToolBarComboBoxButton(uiID, iImage, dwStyle, iWidth) {
}
virtual CComboBox* CreateCombo(CWnd* pWndParent, const CRect& rect) {
CComboBox* pWndCombo = new CComboBox;
if (!pWndCombo->Create(m_dwStyle, rect, pWndParent, m_nID))
{
delete pWndCombo;
return NULL;
}
pWndCombo->AddString(L"TAKO");
pWndCombo->AddString(L"いか");

return pWndCombo;

}
virtual void Serialize(CArchive& ar) {
CMFCToolBarComboBoxButton::Serialize(ar);
}
};

この場合にSerializeを実装してないと、内部的に初期化やレジストリ保存等を行ったときにCFindComboButton が復元されないのでうまくいかないといったことが生じます。

あと、ComboBoxの初期データをどこで設定すればいいかということですが、これはいま調査中です。
この例ではCreateCombo()で入れてみました。

CMFCMenuBarではリソース固定のメニューしかうまく操作できないのか?

MFC4.0の頃のアプリで最新のMFCに移行するのに
メニューを書き換えても更新されないし、リストアするとメニューの一部がなくなる現象にはまりました。

MDIのアプリのメニューを、単一のメニューリソースからでなく、複数のリソースをマージして作り、それをDocumentTemplateのm_hMenuSharedにいれるようにしていたのですが、
これをCMFCMenuBarで実装するようにしました。
そうするとフレームワークはレジストリに現在のメニューの状態を保存するのですが、
あるとき、一部のメニューを表示しなくなり、初期状態に戻すを行っても、一向に直りません。
最終的にレジストリから保存データを全部消すとやっともとに戻りました。

MFCのソースを追っていくと、CMFCMenuBarでは、初期状態に戻すというのは、DocumentTemplateのm_hMenuSharedに戻すのではなく、DocumentTemplateのメニューのリソースIDからメニューを組み立てなおすうようになっていました。
これでは、複数のメニューをマージして、DocumentTemplateのm_hMenuSharedを作るというのが、まったく意味を成さなくなっていますね。。。

困り果てたあげく、CMFCMebuBarを継承したクラスを作成し、SaveState()とRestoreOriginalState()の2つのOverride関数をoverrideして、この処理をなにもしない処理にしました。
これによりレジストリに保存することはできなくなりましたが、メニューの一部がなくなるという悲惨な現象はいまのところなくなりました。
なんかいい方法はないものですかね。。
プロフィール

chattera.net

Author:chattera.net
フリーでソフト開発の仕事をしています。
自作したこのチャットシステムは、何か世の中に役に立つこともあるかと思いますので、お呼びがかかるとうれしいですね。

連絡先は chatteranet@gmail.com です。

また、ソフト開発関連のお誘いもうけたまわっております。

最新記事
最新コメント
最新トラックバック
月別アーカイブ
カテゴリ
検索フォーム
RSSリンクの表示
リンク
ブロとも申請フォーム

この人とブロともになる

QRコード
QR
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。