チェックボックスの位置を変えるには?

[戻る]
ささぴー 2001/05/18(金) 01:28:08
チェックリストボックスでチェックボックスの位置を変更したいのですが、
可能でしょうか?

例えば、"ABCD □ 123456"等途中にチェックボックスを表示したいのです。
VC6.0MFCにて開発しております。
ご存知のかたがいらっしゃればresをお願いします。

Bun 2001/05/18(金) 08:03:46
別にスタティックを貼るわけにはいかないのでしょうか?

Bun 2001/05/18(金) 08:24:11
たくさんあって、スタティックを貼るのがめんどうってことですかね。

CreateWindow()のHelpに BS_***の部分があります。

このあたりを見れば、どんなことができるか見当がつきます。

Bun 2001/05/18(金) 09:24:35
> チェックリストボックスで

すみません。読んでませんでした。
チェックボタンと勘違いしていました。m(__)m

ku 2001/05/18(金) 13:48:49
調べた結果分かった方法を書いておきます。面倒です。
MFCのソースから見るとたぶん簡単な方法はないでしょう。
下の方に見えている「チェックリストボックスの途中から表示させるには」
というのを参考にしてます。
これは
ABC□あいうえお
XYZ□かきくけこ
のようなチェックボックスが固定位置の場合の方法です。
A□あいうえお
XYZ□かきくけこ
のようにやる場合は、AddStringで文字列のアドレスを渡すのではなく
チェック用の座標+文字列の構造体のアドレスを渡すように変更しないと
面倒になりそうです。
長いから抜けがあるかも。

 1.リストボックスを追加する。
   「スタイル」の「オーナー描画」−「固定」、「文字列あり」−「チェック」
 2.winctrl3.cppの内容をコピーしmywinctrl3.cppを作成する。
   インクルードを追加する。
#include <malloc.h>
#include "mywinctrl3.h"
 3.afxwin.hからCCheckListBoxのクラス定義をコピーしmywinctrl3.hを作成する。
   ヘッダの内容を
#if !defined(__CMYCHECLISTBOX_INC_H__)
#define __CMYCHECLISTBOX_INC_H__
  〜 内容 〜
#endif // !__CMYCHECLISTBOX_INC_H__
  で括る。
   下記のメンバを追加する。
public:
    ~CMyCheckListBox();
private:
    HBITMAP m_hbitmapCheck;
    SIZE m_sizeCheck;
 4.コンストラクタとデストラクタをmywinctrl3.cppに追加する。
CMyCheckListBox::CMyCheckListBox()
{
    m_cyText = 0;
    m_hbitmapCheck = NULL;
    m_sizeCheck.cx = m_sizeCheck.cy = 0;
    CBitmap bitmap;
    bitmap.LoadBitmap(AFX_IDB_CHECKLISTBOX_95);
    BITMAP bm;
    bitmap.GetObject(sizeof (BITMAP), &bm);
    m_sizeCheck.cx = bm.bmWidth / 3;
    m_sizeCheck.cy = bm.bmHeight;
    m_hbitmapCheck = (HBITMAP)bitmap.Detach();
}
CMyCheckListBox::~CMyCheckListBox()
{
    if (m_hbitmapCheck != NULL) {
        ::DeleteObject(m_hbitmapCheck);
        m_hbitmapCheck = NULL;
    }
}
 5.mywinctrl3.cppのpChecklistStateの定義の行と
   「pChecklistState->」(こっちはこの文字列だけで行ごとは削除しない)を削除する。
 6.プロジェクトにmywinctrl3.cppとmywinctrl3.hを追加する。
 7.mywinctrl3.cppから下記のコードを削除する。
  a)
#ifdef AFX_CORE4_SEG
#pragma code_seg(AFX_CORE4_SEG)
#endif
  b)_AFX_CHECKLIST_STATE関連
    クラス定義やEXTERN_PROCESS_LOCALの行
 8.mywinctrl3.cppとmywinctrl3.hのCCheckListBoxをCMyCheckListBoxに置き換える。
 9.ClassWizardでリストボックスの変数を追加する。
   メンバ変数:m_ListBox
   カテゴリ:コントロール
   変数のタイプ:CListBox
   ヘッダにCListBox m_ListBox;という行があるので
   CMyCheckListBox  m_ListBox;にする。
   ついでに、#include "mywinctrl3.h"を追加する。
10.まずはここでビルドできるのでビルドする。
11.ソースの上の方に
#define INS_STR_PLUS_X (100)
   を定義する。
12.CMyCheckListBox::PreDrawItemの
            CRect rectCheck = drawItem.rcItem;
            を下記のようにする。
            drawItem.rcItem.left += INS_STR_PLUS_X;
            CRect rectCheck = drawItem.rcItem;
13.CMyCheckListBox::InvalidateCheckとCMyCheckListBox::InvalidateItemと
   CMyCheckListBox::CheckFromPointを修正する。
void CMyCheckListBox::InvalidateCheck(int nIndex)
{
    CRect rect;
    GetItemRect(nIndex, rect);
    rect.left = INS_STR_PLUS_X;
    rect.right = rect.left + m_sizeCheck.cx + 2;
    InvalidateRect(rect, FALSE);
}
void CMyCheckListBox::InvalidateItem(int nIndex)
{
    CRect rect;
    GetItemRect(nIndex, rect);
    rect.left += INS_STR_PLUS_X;
    InvalidateRect(rect, FALSE);
}
int CMyCheckListBox::CheckFromPoint(CPoint point, BOOL& bInCheck)
{
    // assume did not hit anything
    bInCheck = FALSE;
    int nIndex = -1;
    if ((GetStyle() & (LBS_OWNERDRAWFIXED|LBS_MULTICOLUMN)) == LBS_OWNERDRAWFIXED)
    {
        // optimized case for ownerdraw fixed, single column
        int cyItem = GetItemHeight(0);
        if (point.y < cyItem * GetCount())
        {
            nIndex = GetTopIndex() + point.y / cyItem;
            if (point.x >= INS_STR_PLUS_X - 2 &&
                point.x <= INS_STR_PLUS_X + m_sizeCheck.cx + 2)
                ++bInCheck;
        }
    }
    else
    {
        // general case for ownerdraw variable or multiple column
        for (int i = GetTopIndex(); i < GetCount(); i++)
        {
            CRect itemRect;
            GetItemRect(i, &itemRect);
            if (itemRect.PtInRect(point))
            {
                nIndex = i;
                if (point.x < itemRect.left + m_sizeCheck.cx + 2)
                    ++bInCheck;
                break;
            }
        }
    }
    return nIndex;
}
14.CMyCheckListBox::DrawItemの最後の方の
    if ((lpDrawItemStruct->itemAction & ODA_FOCUS) != 0)
        pDC->DrawFocusRect(&(lpDrawItemStruct->rcItem));
   を下記のように変更します。
    if ((lpDrawItemStruct->itemAction & ODA_FOCUS) != 0) {
        CRect rcFocus(lpDrawItemStruct->rcItem);
        rcFocus.left = 0;
        pDC->DrawFocusRect(rcFocus);
    }
15.CMyCheckListBox::DrawItemをコピーしてCMyCheckListBox::DrawItem2を作る。
   CMyCheckListBox::DrawItem2の14で追加した行(DrawFocusRect関連)を削除する。
16.CMyCheckListBox::PreDrawItemの最初の方を下記のように修正。
{
    DRAWITEMSTRUCT drawItem;
    memcpy(&drawItem, lpDrawItemStruct, sizeof(DRAWITEMSTRUCT));
    DrawItem2(&drawItem);
    if ((((LONG)drawItem.itemID) >= 0) &&
        ((drawItem.itemAction & (ODA_DRAWENTIRE | ODA_SELECT)) != 0))
17.winctrl3.cppの下の方にあるこんなのも削除しても大丈夫みたいなので削除する。
#ifdef AFX_INIT_SEG
#pragma code_seg(AFX_INIT_SEG)
#endif

#pragma warning(disable: 4074)
#pragma init_seg(lib)

このままではAddString/InsertStringとかした文字列を2回表示するだけなので
その辺は直す必要があります。
後から書いた□とか文字とかが上書きするので、その辺も調整する必要があります。

古いスレッドには追加発言できません。