EditBoxの追記制限

ActiveBasicでのプログラミングでわからないこと、困ったことなどがあったら、ここで質問してみましょう(質問を行う場合は、過去ログやWeb上であらかじめ問題を整理するようにしましょう☆)。
返信する
メッセージ
作成者
初心者

EditBoxの追記制限

#1 投稿記事 by 初心者 »

下記の方法でEditBoxに表示(追記)しています。
(過去ログから見つけた方法なので、詳細はわかりませんが・・・)

Dim hEdit As HWND
Dim Len As Long
hEdit=GetDlgItem(hMainWnd,EditBox1)
Len=GetWindowTextLength(hEdit)
SendMessage(hEdit,EM_SETSEL,Len,Len)
SendMessage(hEdit,194,0,writeData As Long)

上記で、永遠と追記していくと、EditBoxの限界点で表示が停止してしまいます。

MAX値を指定し、古い表示を忘れ新しい表示を追記したいのですが、方法を教えてください。
ゲスト

#2 投稿記事 by ゲスト »

どうすれば良いか適当に解説

エディットコントロールにある文字の長さ=length1
追記する文字列の長さ=length2
エディットコントロールの限界値=limit
とします

length1+length2>limitであれば容量を超えてしまって追記できないので
エディットコントロールの内容を確保しておいたバッファ(大きさはlength1+length2+1)に取得
このバッファにlstrcatで追記する文字列を連結
このままWM_SETTEXTでバッファのアドレスを指定するとlength1+length2-limit Byteはみ出してしまうので
SendMessage(エディットコントロールのハンドル,WM_SETTEXT,バッファのアドレス+length1+length2-limit,0)
のように書き込み始めるアドレスをずらす
最後にカーソルを最後尾に持っていく
これでできるはず

とまあここまで書いておいて何なんですが、こんなもん書かなくていいと思う
せっかく人がやる気になってんのにこんなどうでもいい所で不毛なコード書かざるを得なくなるとテンションが下がるしね
(個人的にはこれがABが流行らない根本的な理由だと思ってる)

話が逸れました
プロジェクトに↓を加えて下さい
http://www.2chab.net/uploader/src/up0009.sbp

' TODO: この位置にグローバルな変数、構造体、定数、関数を定義します。
の位置に
Dim pclw As *CLogWindow
を記述
メインウィンドウのCreateイベント内に
pclw = New CLogWindow(GetDlgItem(hMainWnd,エディツトコントロールのID))
を記述
メインウィンドウのDestroyイベント内に
Delete pclw
を記述

後は普通のエディットコントロールと同じように使えるはずです。
上限の設定は
SendMessage(エディットコントロールのハンドル,EM_SETLIMITTEXT,上限サイズ,0)
でできます
デフォルトは32KByte=32*1024Byteです
7
記事: 473
登録日時: 2005年5月31日(火) 18:51
お住まい: 新潟県
連絡する:

#3 投稿記事 by 7 »

文字列を追加したいっていう要望は今までに何回かありましたけど、文字列を追加したいけどはみ出る、そんな場合先頭の文字列を切り捨てていきたいっていう要望は今までありませんでしたね。

エディットボックス大好き人間、ここはオレの出番だろぉぉぉぉ、という訳で関数を作ってみました。

コード: 全て選択

' コマンドボタン1が押された時に文字列を追加します
Sub MainWnd_CommandButton1_Click()
	Edit_AddTextEx(GetDlgItem(hMainWnd,EditBox1),"追加したい文字列")
End Sub
関数の名前はちょっと適当です...。
原理というかはゲストさんの説明を読めばなんとなく分かるのではないかと。

追記。
何か忘れてる気がすると思ったら、操作できるバイト数より追加する文字列のバイト数が大きかった場合の処理をしてなかったので修正しました。
初心者

#4 投稿記事 by 初心者 »

ゲスト様
ありがとうございます。
試しましたが、コンパイル時にDestroyイベントにて追加した行でエラーが出ます。

>Delete pclw

MainWnd.sbp(61) - 定数式にリテラル値、または定数以外のものが含まれています
MainWnd.sbp(61) - Delete演算子にポインタ以外の型が指定されています

よろしくお願いします。
------------------------------
7様
ありがとうございます。
試しましたが、コンパイルは正常に終了しますが実行時にエラーがでます。

コンパイラのエラー
 スレッド(&h17FC)でアクセス違反がありました(EPI=&H0012CF98)

function.sbp 316行
>_Support_tan=x/(1-t)

Windowsのエラー
 BasicCompiler.exeは動作を停止しました。
 問題が発生したため、プログラムが正しく動作しなくなりました。・・・

トレースすると、Edit_GetLimitText()からfunction.sbpに行きエラーに
なっている様子です。
>Function Edit_AddTextEx(ByVal hWnd As HWND,ByVal lpString As LPSTR) As BOOL
>Dim lpStr As LPSTR
>Dim length[1] As Long, limit As Long
>
>limit=Edit_GetLimitText(hWnd)


使用OS:WindowsVista HomePremium

よろしくお願いします。
7
記事: 473
登録日時: 2005年5月31日(火) 18:51
お住まい: 新潟県
連絡する:

#5 投稿記事 by 7 »

> 7様
> ありがとうございます。
> 試しましたが、コンパイルは正常に終了しますが実行時にエラーがでます。
こっちでは何も問題ないんですけどねぇ...。

> 使用OS:WindowsVista HomePremium
ActiveBasicのバージョンはなんでしょう?
件のコードはVer.5.0 CP3で作ったものなので他のバージョンだった場合、うまく動かない可能性があります。
Vistaっていうのもなんとなく関係あるのかもしれませんけど...?
初心者

#6 投稿記事 by 初心者 »

>>ActiveBasicのバージョンはなんでしょう?

4.24です。
よろしくお願いいたします。
初心者

#7 投稿記事 by 初心者 »

追伸です。
>>Vistaっていうのもなんとなく関係あるのかもしれませんけど...?
Xpで試しました。
同じ個所で似たようなエラーになり、コンパイラが死にます。

よろしくお願いいたします。
7
記事: 473
登録日時: 2005年5月31日(火) 18:51
お住まい: 新潟県
連絡する:

#8 投稿記事 by 7 »

> >>ActiveBasicのバージョンはなんでしょう?
>
> 4.24です。
互換性の問題でしたね。
初心者

#9 投稿記事 by 初心者 »

7様

ありがとうございます。
無事動きました。

教えて頂いたコードに、コントロールコードであれば<02>の様に表示する機能を追加してみました。
一応は動くのですが、以下の対策を教えてください。

1、メモリ確保の方法が悪く、大量のコントロールコードでメモリが溢れる。
  何か良い解決策は有りませんか?
2、なぜか、free(dummy)を実行するとEXEが落ちる。

宜しくお願いいたします。
konisi
記事: 893
登録日時: 2005年7月25日(月) 13:27
お住まい: 埼玉県東松山市
連絡する:

#10 投稿記事 by konisi »

まだ実行していないので詳しい事は全く言えないんですが、callocの下のlstrcatは文字列が長くなると重くなるので、dummy_length等の名前で現在の文字の長さを保管しながらmemcpyした方が安定します。

コード: 全て選択

'before
lstrcat(dummy , tp)
'after
Dim dummy_length As Long

memcpy(dummy+dummy_length,tp,lstrlen(tp))
dummy_length+=lstrlen(tp)
あと、それより前にForブロックがあるんですが、Toの値は関数にしないほうがいいです。実行速度低下の要因になります。

コード: 全て選択

'before
For I = 0 To lstrlen(lpString) -1
'after
Dim lpStringLength As Long
lpStringLength=lstrlen(lpString)-1
For I = 0 To lpStringLength
メモリ確保量の問題は、溢れそうになったらreallocするとか、あるいは全てが変換対象のコードだった場合を想定してメモリを元の文字列の4~5倍の大きさ、確保するとか、他にも変換する個数を予め数えてから確保し、変換を開始するなど。
日本語文字列に対するチェックが甘すぎるようですが・・・。

それと、途中で抜ける時にどうもfreeし忘れているように見えるんですが・・・。

freeについては、原因が解りません。
Website→http://web1.nazca.co.jp/himajinn13sei/top.html
ここ以外の場所では「暇人13世」というHNを主として使用。

に署名を書き換えて欲しいと言われたので暇だしやってみるテスト。
7
記事: 473
登録日時: 2005年5月31日(火) 18:51
お住まい: 新潟県
連絡する:

#11 投稿記事 by 7 »

これから仕事なので細かくチェックしてないのですが以下のように書いてみました。 要は、指定された文字列の中に含まれる制御コードをパっと目に見える形に置換したいっていう要望ですよね。
まずは文字列の置換関数を考えてみた方がスッキリするかもしれません。
7
記事: 473
登録日時: 2005年5月31日(火) 18:51
お住まい: 新潟県
連絡する:

#12 投稿記事 by 7 »

> 要は、指定された文字列の中に含まれる制御コードをパっと目に見える形に置換したいっていう要望ですよね。
> まずは文字列の置換関数を考えてみた方がスッキリするかもしれません。
朝はちょっと考えが浅くてオススメしただけだったんですが、やっぱり特定の制御コードだけを別の文字列に換えるような関数を作った方がいいと思います。

今回作った Edit_AddTextEx という関数はテキストボックスに文字列を追加し、エディットボックスが操作できる容量を超えるようだったらその分先頭の文字列を切り捨てるという関数ですが、この関数の中に他のことをするようなコードを潜り込ませるのはあまりいい事ではありません。

いくつかの関数をまとめて一つの関数にするメリットはいくつかありますが、その一つ、「コードの再利用」という目的から離れて行ってしまっているからです。(僕個人の考えですけど)

あと、「制御コードを別の文字列に変換し、その文字列をエディットボックスに追加する。エディットボックスの容量以上になる場合、先頭文字列を切り捨てる」
という関数は非常に有効範囲が狭く応用が利きません。
「制御コード(特定の文字列)を別の文字列に変換する」
「文字列をエディットボックスに追加する。エディットボックスの容量以上になる場合、先頭文字列を切り捨てる」
こういう風に役目毎に関数を切り分けることで応用が利きやすくなります。

質問の内容と関係ない説明でウザいかもしれませんね...。

追記。

ハンドルネームについても一つ。
あなたは今までに投稿してきた「初心者」さんと同一人物ですか?
あまり考える必要はありませんがちょくちょくかぶったり、かぶるようなハンドルネームはちょっと...。
もし次に新しいトピックを作る場合、もうちょっとユニークなハンドルネームでお願いします。
最後に編集したユーザー 7 [ 2007年4月20日(金) 18:06 ], 累計 1 回
初心者

#13 投稿記事 by 初心者 »

konisi様、7様

アドバイスありがとうございます。
勉強になりました。
返信する