ページ 13

キーワードの色分け(2)

Posted: 2006年3月15日(水) 18:01
by yu0627
 ↓のほうでやっていましたが、色々とあったのでここに移行させていただきます。
 リッチエディットでActiveBasicコードの色分けをやっております。
この程、色分けを全て終了することができました。しかし、それでも問題があります。

①それぞれのキーワードを選択しながら色変更をしているので、色変更する前の状態に戻せません。
②あまりにも重たいです。文字ひとつ入力しただけで一秒近くまたされるときもあります。

 ①について解決方法と考えているのは、リッチエディットのスクロールバーの位置を色変更前に記録し、変更後に記録した位置に戻すと言うことです。これは可能でしょうか。
 ②については、誰かプログラムの「ムダ」を見つけてくれませんでしょうか。
 今回は、現在の状態のソフトを公開したいと思います。
http://www.exfiction.net/~yu0627/temp/AB_T_RichEdit.zip

現在のコードはこちら↓

Posted: 2006年3月15日(水) 18:41
by konisi
見間違えでなければ、
Const MaxText = 102400 '最大容量(byte)default=64K
の部分の数値は100キロバイトです・・・。64キロバイトは65536かと。

返信@yu0627

Posted: 2006年3月15日(水) 20:56
by yu0627
> 見間違えでなければ、
> Const MaxText = 102400 '最大容量(byte)default=64K
> の部分の数値は100キロバイトです・・・。64キロバイトは65536かと。
あの~。そこはリッチエディットの初期容量が64KBということです。気にしないで下さい。

Posted: 2006年3月15日(水) 21:34
by みどるべあ
MainWnd.sbpの40行目付近

コード: 全て選択

GetModuleFileName(GetModuleHandle(0), lpstrFolderPath, MAX_PATH)
i=lstrlen(lpstrFolderPath)-1
iはGetModuleFileNameの戻り値でも取得できるので

コード: 全て選択

i=GetModuleFileName(GetModuleHandle(0), lpstrFolderPath, MAX_PATH)
とできます。

Posted: 2006年3月15日(水) 22:04
by ノッチ
現状のソースを見るとリッチエディットに入力されている全ての文字に対して
色の変更処理を行っているようですが、これでは入力された文字が多くなる、
キーワード数が多くなるにつれ処理がどんどん重たくなっていきます。
処理を高速にするには簡単に思いつく限り、
1) 色の変更処理を画面に表示されている部分に限定する
2) 変更された行にのみ色変更処理を行う
といった感じでしょうか。

2)を導入できればベストだと思いますが、いかにもバグを誘発しそう(貼り付け
やアンドゥ時等)なので、1)を検討するのがよろしいかと思います。
リッチエディットは使用したことがないのですが、EM_LINELENGTHやEM_GETFIRSTVISIBLELINE
なんかを駆使すれば画面内の文字を取得できる(?)ので、
その画面バッファを使用して変更すれば処理は格段に早くなると思います。
ただ画面をスクロールする度に画面内の文字をバッファに確保、変更を行う
ので、スクロールさせる時は逆に時間がかかってしまうかもしれません。

返信@yu0627

Posted: 2006年3月16日(木) 10:40
by yu0627
ノッチさん、みどるべあさん、返信ありがとうございます。
これは携帯のフルブラウザから投稿していますので、正式な返信はパソコンから行いたいと思います。

返信@yu0627

Posted: 2006年3月16日(木) 20:19
by yu0627
 みどるべあさん、ノッチさん、ありがとうございます。
現在コードを見直しているところです。
2)を導入できればベストだと思いますが、いかにもバグを誘発しそう(貼り付け
やアンドゥ時等)なので、1)を検討するのがよろしいかと思います。
リッチエディットは使用したことがないのですが、EM_LINELENGTHやEM_GETFIRSTVISIBLELINE
なんかを駆使すれば画面内の文字を取得できる(?)ので、
その画面バッファを使用して変更すれば処理は格段に早くなると思います。
ただ画面をスクロールする度に画面内の文字をバッファに確保、変更を行う
ので、スクロールさせる時は逆に時間がかかってしまうかもしれません。
 ありがとうございます。僕もそれを考えたのですが、どうやって何列表示されているか、表示されている最初の文字の位置と最後の文字を取得するかで悩んでいます。
また、どうやってスクロールバーが移動したのを取得するのか、スクロールバーの位置をどうやって記録するか、どうやってスクロールバーの位置を設定するか、それが分かれば解決...、という分けには行かないと思いますが、うまく行くと思います。

Re: 返信@yu0627

Posted: 2006年3月16日(木) 23:16
by ノッチ
> ありがとうございます。僕もそれを考えたのですが、どうやって何列表示されているか、表示されている最初の文字の位置と最後の文字を取得するかで悩んでいます。

「リッチエディット 表示行数」で検索したらまさしくその通りのものが見つかりました。

http://forums.belution.com/ja/vc/000/170/57s.shtml

> また、どうやってスクロールバーが移動したのを取得するのか、スクロールバーの位置をどうやって記録するか、どうやってスクロールバーの位置を設定するか、それが分かれば解決...、という分けには行かないと思いますが、うまく行くと思います。

スクロールバーが移動する時はWM_VSCROLL(縦)というメッセージを飛ばします。
恐らくこのメッセージはリッチエディットに対して送られてくるので、
リッチエディットをサブクラス化してWM_VSCROLLを捕まえてGetScrollPosなんかで
グローバル変数にスクロールバーのポジションを保存、処理を行った後、
SetScrollPosでポジション再指定とすればいいのかな?といったところです。

WM_VSCROLLがもしかしたらhMainWndに送られてくるかもしれませんし、
そもそもうまくいかないかもしれませんが、お試しください。

返信@yu0627

Posted: 2006年3月18日(土) 15:16
by yu0627
 ノッチさん、ありがとうございます。
言われたようにやってみたところ、かなり速くなりました。
ただ、どうやって画面がスクロールしたかを取得し、色変更をするかで悩んでおります。
普通に取得できるのですが、文字色変更時にスクロールするので、それで無限ループに入ってしまい、終いには落ちてしまいます。
タイマーでやってみたのですが、ちらつきます。
また、スクロールバーの位置を取得し、元に戻しても、位置が動いてしまいます。
どうすればいいんでしょうか...。

返信@yu0627

Posted: 2006年3月19日(日) 22:44
by yu0627
 あれから色々と試行錯誤をし、色々な問題を解決しました。
 反応の遅さについては、貼り付け処理時に全てのキーワード色を一括して変更し、
通常文字変更時には画面内のみキーワード色を変更することにしました。
そして、大幅な高速化が出来たわけですが、やはりスクロールバーの位置記録と位置セットは
うまくいきません。今回からはその問題のコード部分のみ公開しようと思います。

リッチエディット作成 スクロールバー位置取得&位置セット こうしても、スクロールバーの位置は正常にセットされるのですが、表示位置がずれてしまいます。
なんか良い方法はないですかね。

現在のプログラムはこちら
http://www.exfiction.net/~yu0627/temp/T_RichEdit.zip

#追記
青文字にするキーワードは、以下ので全てでしょうか

Re: 返信@yu0627

Posted: 2006年3月20日(月) 17:15
by ノッチ
現状のソースがわからないので的確なコメントは難しいですが、
スクロールバーの位置取得設定関数が云々ではなく、その処理を行うタイミング
が原因ではないかと思われます。(もしかしたら違うかも)

GetScrollInfoを行った後debugで構造体の内容確認。
いくつか処理を行うごとにdebugやMessageBoxで処理を止めて状況を見る。
を行うとわかりやすいと思います。
VisualStudioをインストールするとついてくるSPY++ってのを使うとわかりやすい
んですけど。なければdebug等で手動でやるしかないです。

また、EM_SETEVENTMASKでリッチエディットから送るメッセージを選択できます。
EM_SETEVENTMASKでぐぐるとでてくる"yokohama.cool.ne.jp"のページはわかりやすいです。
このメッセージを処理することで現象が変わるかもしれません。

返信@yu0627

Posted: 2006年3月20日(月) 20:37
by yu0627
 ノッチさん、ありがとうございます。
現状のソースがわからないので的確なコメントは難しいですが、
スクロールバーの位置取得設定関数が云々ではなく、その処理を行うタイミング
が原因ではないかと思われます。(もしかしたら違うかも)
 これについてですが、スクロールバーの位置を記録するのは文字色を変更する前、
スクロールバーの位置を設定するのは文字色を変更した後です。
どうやら、スクロールバーと表示内容はスクロールバーだけを操作してもいけないようです。
ですので、もし一番上の行が違っていた場合には元の位置まで戻すようにしたのですが、うまくいきません。
 選択してもウインドウをスクロールしないように出来ないでしょうか。

今更ですが。

Posted: 2006年3月21日(火) 23:26
by konisi
NewとDebugも色が変わると思います。>>yu0627さん

Posted: 2006年3月22日(水) 01:27
by マティ
実際の改造に対する助言は、知識不足で出来ませんが、改善方法の1つを提案します。

SetKeywordColor()を呼び出すと、全データを再処理し画面のみ再設定していますが、
修正のあった範囲を取得する事は出来ないのでしょうか?

取得できるなら、修正のあった範囲に、*が無いか確認し、もしあった場合に前後の文字を確認します。
/*または*/なら全体の処理を行い、(複数行にまたがる命令)
無い場合は、その1行のみを処理するようには出来ないでしょうか?

リッチテキストをコントロールした事が無いので無責任な発言になりましたが、
変更の無い部分は処理しない、これが一番効きます。

できた!?表示位置を元に戻す

Posted: 2006年3月22日(水) 13:59
by ノッチ
手元の簡単環境では多少画面の乱れはありますが、スクロールせずに入力が
できました。
以下を'スクロールバーを元の位置に戻す 処理のあとに入れて下さい。

コード: 全て選択


'スクロールバーを元の位置に戻す
SetScrollInfo(hEdit, SB_VERT, VScrollInfo, TRUE)
SetScrollInfo(hEdit, SB_HORZ, HScrollInfo, TRUE)
SendMessage(hEdit,WM_HSCROLL,HScrollInfo.nPos*&H10000+SB_THUMBTRACK,0)
SendMessage(hEdit,WM_VSCROLL,VScrollInfo.nPos*&H10000+SB_THUMBTRACK,0)
やってることは、「スクロールバーを操作しましたよ」とリッチエディットに
うそ情報を与えて表示位置を更新させているだけです。
先にWM_VSCROLLをしてからWM_HSCROLLを行うと微妙にずれますのでこのままの
順番で。
SetKeywordColor関数の内容が手元にあるものとyu0627さんが持っているもので
恐らく違うので、違う動きをするかもしれませんが試す価値はあると思います。