エディットボックスの入力バイト数を指定するには?

解決


さち  2006-02-18 01:50:38  No: 60759

連続ですみません。
以前も似たような質問をさせていただきましたが、再度質問させていただきます。

質問内容は件名の通りで、
エディットボックスに入力バイト数を指定したいのですが
どうすればいいのでしょうか?

当方UNICODEを使用しているので、LimitTextを使っても無駄でした…
(文字数制限になってしまう)

何か対策があればアドバイスお願いいたします。

<<WindowsXP VC++.NET2003 MFC UNICODE使用>>


kure  2006-02-18 02:07:50  No: 60760

UTF-16は1文字2バイトですよ。
12バイトに制限するなら12/2で
6文字制限にするってのはだめなんでしょうか??

もしかしてSJIS換算でのバイト数のこと?


Blue  2006-02-18 02:08:36  No: 60761

CEditクラスをサブクラス化してチェックすることになるのかな。


さち  2006-02-22 22:41:25  No: 60762

返信遅くなりましてすみません;
(風邪でぶっ倒れてました…orz)

やはりそう簡単にはいかなそうですね…。。<<バイト数指定

>もしかしてSJIS換算でのバイト数のこと?
SJIS換算なのでしょうか。
半角は1バイト、全角は2バイトという認識でいるのですが…

>CEditクラスをサブクラス化
サブクラス化とはなんなのか分からないのでちょっと調べてみます。


みい  2006-02-22 22:51:19  No: 60763

> SJIS換算なのでしょうか。
> 半角は1バイト、全角は2バイトという認識でいるのですが…
前のスレッドの時にεπιστημηさんから
> コンパイル時にUNICODEになってませんか?
> UNICODEなら半角/全角を問わず1文字=1wordです(一般に)。
って指摘されてますけど…


Blue  2006-02-22 23:03:11  No: 60764

http://forums.belution.com/ja/vc/000/350/39s.shtml
も参考にしてみてください。逆で悩んでいるようですけど。

> その中で、GetWindowTextLengthWで文字数を調べて制御する。

GetWindowTextLengthAでバイト数を調べて制御する。
となります。

ただ、あちらで tetrapodさん がおっしゃっているように、
エディットボックスで無理して処理させる必要はない気がします。


Blue  2006-02-22 23:07:44  No: 60765

追記)

サブクラス化するときに、
全体バイト数 - 1 の時は全角入力できない 等の処理を入れないといけませんので
http://forums.belution.com/ja/vc/000/350/39s.shtml
より多少面倒になります。
(nCharはUNICODEなので半角全角判定はWideCharToMultiByte関数等を使って判定することになるでしょう)


さち  2006-02-22 23:12:24  No: 60766

>> SJIS換算なのでしょうか。
>> 半角は1バイト、全角は2バイトという認識でいるのですが…
>前のスレッドの時にεπιστημηさんから
>> コンパイル時にUNICODEになってませんか?
>> UNICODEなら半角/全角を問わず1文字=1wordです(一般に)。
って指摘されてますけど…

書き方がややこしかったっていうか、間違ってましたね…すみません…
>> 半角は1バイト、全角は2バイトという認識でいるのですが…
半角は1バイト、全角は2バイトで計算したかったのですが、
当方UNICODE使っているためそこで苦戦してます。

>http://forums.belution.com/ja/vc/000/350/39s.shtml
>も参考にしてみてください。逆で悩んでいるようですけど。

>> その中で、GetWindowTextLengthWで文字数を調べて制御する。

>GetWindowTextLengthAでバイト数を調べて制御する。
>となります。

>ただ、あちらで tetrapodさん がおっしゃっているように、
>エディットボックスで無理して処理させる必要はない気がします。

ありがとうございます。参考にしてみます。
逆で悩んでる人もいるのですね…。。


さち  2006-02-25 00:12:07  No: 60767

なんとか解決しました。
いろいろありがとうございました><


Blue  2006-02-25 03:05:52  No: 60768

> なんとか解決しました。
どう解決したか、きちんとかきましょう。


訪問者  2007-02-01 19:29:08  No: 60769

参考にしようとしてたどり着きましたが・・・。
最後に答えは無しですか・・。


Blue  2007-02-02 05:01:14  No: 60770

>参考にしようとしてたどり着きましたが・・・。
>最後に答えは無しですか・・。
一応、作ったコードが残っていたので載せときます。
なんせ1年ほど前なので記憶がほぼないです。

開発環境:WindowsXp Pro SP2/VS2005 Pro
◎ByteLimitEdit.h
#pragma once

// CByteLimitEdit

class CByteLimitEdit : public CEdit
{
    DECLARE_DYNAMIC(CByteLimitEdit)

public:
    CByteLimitEdit();
    virtual ~CByteLimitEdit();

protected:
    DECLARE_MESSAGE_MAP()
public:
    afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);
    LRESULT OnPaste( WPARAM, LPARAM );
public:
    // 入力最大バイト数
    unsigned int m_nLimit;
public:
    // 最大入力バイト数
    void SetLimitLength(unsigned int nLimit);
    // 入力可能バイト数
    int GetBlankLength(void);
    // 選択中文字列バイト数取得
    int GetSelectionByteLength(void);
};

◎ByteLimitEdit.cpp
// ByteLimitEdit.cpp : 実装ファイル
//

#include "stdafx.h"
#include "ByteLimitEditTest.h"
#include "ByteLimitEdit.h"

#include <afxole.h>

// CByteLimitEdit

IMPLEMENT_DYNAMIC(CByteLimitEdit, CEdit)

CByteLimitEdit::CByteLimitEdit()
: m_nLimit(0)
{

}

CByteLimitEdit::~CByteLimitEdit()
{
}

BEGIN_MESSAGE_MAP(CByteLimitEdit, CEdit)
    ON_WM_CHAR()
    ON_MESSAGE( WM_PASTE, OnPaste )
END_MESSAGE_MAP()

// CByteLimitEdit メッセージ ハンドラ

void CByteLimitEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
    // TODO: ここにメッセージ ハンドラ コードを追加するか、既定の処理を呼び出します。
    if ( m_nLimit && !_istcntrl( nChar ) )
    {
        int nBlank = this->GetBlankLength();

        if ( nBlank <= 0 )
        {
            ::MessageBeep( MB_OK );
            return;
        }
        if ( nBlank == 1 )
        {
#ifdef _UNICODE
            // ※UNICODEサロゲート無視!
            WCHAR szTemp[ 2 ] = { nChar };
            if ( ::WideCharToMultiByte( CP_ACP, 0, szTemp, -1, NULL, 0, NULL, NULL ) > 2 )
            {
                ::MessageBeep( MB_OK );
                return;
            }
#else
            static bool bMultiByteChar = false;
            if ( !bMultiByteChar && _ismbblead( nChar ) )
            {
                bMultiByteChar = true;
                ::MessageBeep( MB_OK );
                return;
            }
            if ( bMultiByteChar )
            {
                bMultiByteChar = false;
                return;
            }
#endif  
        }
    }
    CEdit::OnChar(nChar, nRepCnt, nFlags);
}

// 最大入力バイト数
void CByteLimitEdit::SetLimitLength(unsigned int nLimit)
{
    m_nLimit = nLimit;
}

// 入力可能バイト数
int CByteLimitEdit::GetBlankLength(void)
{
    return m_nLimit - ::GetWindowTextLengthA( m_hWnd ) + this->GetSelectionByteLength();
}

// 選択中文字列バイト数取得
int CByteLimitEdit::GetSelectionByteLength(void)
{
    int nStart, nEnd;
    this->GetSel( nStart, nEnd );

    const int nLength = nEnd - nStart;
    if ( !nLength )
    {
        return 0;
    }
    // 現在のテキストの取得
    LPSTR lpszBuff = new CHAR[ m_nLimit + 1 ];
    ::GetWindowTextA( m_hWnd, lpszBuff, m_nLimit + 1 );
    // 選択開始位置までインクリメント
    UCHAR* p = _mbsninc( static_cast< const UCHAR* >( static_cast< const void* >( lpszBuff ) ), nStart );
    // 終了位置よりバイト数を算出
    int nByteLength = static_cast< int >( _mbsninc( p, nLength ) - p );
    delete [] lpszBuff;

    return nByteLength;
}

HRESULT CByteLimitEdit::OnPaste( WPARAM, LPARAM )
{
    COleDataObject obj;
    
    if ( obj.AttachClipboard() && obj.IsDataAvailable( CF_TEXT ) )
    {
        HGLOBAL hMem = obj.GetGlobalData( CF_TEXT );
        LPCSTR lpszText = ( LPCSTR )::GlobalLock( hMem );
        size_t nLength = strlen( lpszText );
        ::GlobalUnlock( hMem );

        if ( GetBlankLength() >= static_cast< int >( nLength ) )
        {
            return Default();
        }
    }
    ::MessageBeep( MB_OK );
    return 0;
}


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加