今日は。
また、よろしくお願いします。
先に質問したFormでのことです。
MouseDownは4つになりました。
さて、このFormのRichRdit1には2つのボタンからデータを表示させています。
ボタンBで表示させたデータをmousedownで行のデータを呼び込ませて、処理しています。
このプログラムは下の通りです。
問題は、ボタンAを押してデータを表示させた後で、ボタンBでデータ表示させた場合は、呼び込めなくなる場合があることです。
今日は、全部読み込めませんでしたが、先日、質問しようかと思って試した時は読み込みました。
そうなった場合、このformを終了してもう一度立ち上げたら、読み込めるようになります。
この問題は以前から続いているのですが、delphi6で起こっていたかどうかは覚えていません。
2009では間違いなく起こっていましたし、XE2でも起こっています。
一応、どうなっているかを調べたら、gyoが475になっていました。
空白行を読み込んでいました。
どんな原因が考えられますか。
急いではいませんので、よろしくお願いします。
procedure TForm1.RichEdit1MouseDown(Sender: TObject;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
s:string;
gyo,p,I:integer;
begin
if RichEditFlg=true then
begin
i:=GetScrollPos(RichEdit1.Handle,SB_VERT);
gyo:=((i+y-5) div 17); S:=Copy(RichEdit1.lines[gyo],7,4);
showmessage(IntToStr(gyo));
p:=pos(' ',S);
if P>0 then s:=copy(s,1,p-1);
richedit1.Clear;
richedit1.lines.add(s);
end
end;
デフォルトのフォントが Tahoma で日本語が入っているとそれ以降
フォントが勝手に変わるそして高さが変わるので行ずれが発生する
XE2 + Windows7 で
今試したら、何をやっても正常に読み込むので検証ができなくて困っていますが。
KHE00221さんへ
ありがとうございます。
高さが変わっているようには見えません。
また、表示される行数も変わっていません。
3行目を取得しようとしても、475行とか出たんですが。
高さの違いによる行ずれとは思えません。
今見たら、ボタンAで表示するのは、数字だけです。
データを取得するボタンBでの表示には日本語が入っていますが。
とりあえず、フォントを変更してみます。
作った時からMS明朝でした。
よって、変更しませんでした。
このまえみなさんがリンクを貼ってくれていた
質問するときの注意事項のところは読んでいるのかな・・・
つまりこういうことですよね
MouseDownイベントで行を取得するプログラムを書いているけど
正常に取得できない
この現象は
Delphi6では起きていたか不明
Delphi2009とXE2では発生していた
でいいのかな?
で、今度はこっちからの質問ね?
gyoに475が入るのはおかしいのですよね?
じゃあ正解の数値(期待値)は何かな?
大きく離れています?
1行目をクリックした場合とか
スクロールバーが一番上にある状態
少し下げた状態
期待値と実際値が異なる箇所(上からずれていくと仮定して)
それぞれの実際の値を言ってくれたら
原因がわかりそうです。
って言っても現象はもうでないのですよね・・・。
フォントはOSによる影響もあるからOS名も書いた方がいいかもね
gyoがおかしいのであれば、gyo:=((i+y-5) div 17); の式があるんだから
i または y がおかしいんだよね?
i または y がおかしいから、gyoが期待した値じゃないんでしょ?
じゃ、次に調べることって何?
わかるよね?
自分でもわかってるんじゃない。
i:=GetScrollPos(RichEdit1.Handle,SB_VERT);
gyo:=((i+y-5) div 17);
これを検証すれば終り。簡単だね。
もう少し自分で考えないと、そのうち1行書くごとに質問する羽目になっちゃうぞ。
どうせいつもと同じく馬の耳に念仏、豚に真珠だろうが、一応助言するよ。
取得したい行番号はどういう条件?それを取得するのに最適な関数は?
もし行番号が間違っているなら、正しく取得するための手段をもう一度考え
てみて、そこでわからない部分が出たら再度質問すればいい。
現在表示されている行の最上位行とか、マウスカーソルが今乗っている行数とか、
いろいろあるだろうけど、同じようなことを考えてる人は、過去に山ほどいて、
ネット上にも資料はいっぱいあるよ。
まず要件を確認しよう。自分でも要件、よくわかってないでしょ?
そもそも不確実な計算に頼らず、TRichEditに直接きくというのはナシなんでしょうか。
MouseDownの時点でキャレットがクリックされた位置に移動しているなら
TRichEdit.CaretPos に行番号が入っていますから、そのまま使えるはずです。
そうでなかったら、マウスの位置からCharFromPos→LineFromCharしてやればいいです。
EM_CHARFROMPOSの使い方は以下を参照
http://hiderin.air-nifty.com/delphi/2007/09/index.html
文字位置がわかれば次のようにして行番号がとれます。
line := RichEdit1.Perform(EM_LINEFROMCHAR, 文字位置, 0);
こんばんは。
書き込み、ありがとうございます。
takeさんへ
読んでみましたが、あの通りはできないと思います。
で、詳しく書いたつもりですが。
正常に取得できないではなく、できる時とできないときがあるという意味ですが。
期待値が3,4,5などの時に400番台の数字が入っていたということです。
今日はまたエラーが出まくりました。
理由がはっきりしないので、イラつきます。
スクロールバーについては一番上にある状態ですね。
エラーが出ないときは、ボタンAを押した後なにをしようが出ませんが、出るときはボタンAを押すたびに必ずでるんです。
通りすがりさんへ
i:=GetScrollPos(RichEdit1.Handle,SB_VERT);
これがエラーおこしてます。
i=7718になっていました。
どこをクリックしてもこうなります。
なぜこうなるのかをお聞きしたいんですよね。
ボタンAを押してデータを表示させたら起きることがある。
何か変わるんですかね。
GetScrollPosを初期化するとか、あるんでしょうか。
いつもとおなじはんのうだねさんへ
要件という言葉が何を意味してるのか、よく分かりません。
最適な関数として選んだつもりなんですが、7年ほど前に。
torさんへ
PT:=point(X,Y);
gyo:= RichEdit1.Perform(EM_CHARFROMPOS, 0, Integer(@Pt)) div 46;
これでうまく行が取得できました。
今日はエラーが頻発していますが、ボタンAを押した後も正常に取得できます。
ただ、スクロールしたら正常な値が取得できません。
スクロールしていない場合の値が取れます。
どれだけスクロールしたのかが分かればいいんですよね。
そんな関数ありませんか?
おそらく
i:=GetScrollPos(RichEdit1.Handle,SB_VERT);
を使う前に試して、没にした関数だと思います。
これはスクロールしても大丈夫だったので使用しているんですけど、変なエラーを起こすんですね。
せっかく紹介いただいたのですが、残念です。
ありがとうございました。
皆さん、多くのご教授ありがとうございましたが、解決できず残念です。
また、ご援助をお願いします。
i:=GetScrollPos(RichEdit1.Handle,SB_VERT);
はどれだけスクロールしたかを見る関数でした。
先の投稿の中で勘違いした記述をしてしまいました。
一応
if i>=7718 then i:=i-7718;
を入れてみました。
この文を除けると、ボタンAを押したらエラーが出て、
この文を入れると、ボタンAを押してもエラーは出ません。
実はボタンAを押すと、480行表示するんです。
7718 div 17=482
何か関係ありますよね?
やはり、スクロールバーの初期化がいるんじゃないでしょうか。
i:=setScrollPos(RichEdit1.Handle,0,0,st);
これを挿入しました。
これを入れて実行したら、エラーは出ません。
除けてもエラーは出ません。
これで、しばらく様子を見て問題なければ、解決にします。
通りすがりさん、いつもと同じ反応だねさん
ありがとうございました。
私みたいな年になっても、調べたらできるんですね。
通りすがりさんの「わかるよね」で、頭が働き始めました。
また、質問ができたら来ますので、よろしくお願いします。
procedure TForm1.RichEdit1MouseDown(Sender: TObject;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
s:string; ST:boolean;
gyo,p,I:integer;
begin
if RichEditFlg=true then
begin
i:=setScrollPos(RichEdit1.Handle,0,0,st);
i:=GetScrollPos(RichEdit1.Handle,SB_VERT);
gyo:=((i+y-5) div 17); S:=Copy(RichEdit1.lines[gyo],7,4);
//showmessage(IntToStr(gyo));
p:=pos(' ',S);
if P>0 then s:=copy(s,1,p-1);
richedit1.Clear;
richedit1.lines.add(s);
end
end;
>読んでみましたが、あの通りはできないと思います。
だからそこを努力しましょうよ
読む方大変なんですよほんと
身の回りの人に、ここの質問した文章そのまま
印刷して理解できるのか聞いてもらえます?
原因を考える前に、何書いているのかの解読に
時間と労力かかるんだから
で、せっかくF8とかF10のステップ実行があるし
1行毎に結果がわかるのだから
どこで期待しない動作になっているかを把握できますよね?
で、そこを質問してもらえれば回答しやすいと思うのだけど
質問A
TRichEditのMouseDownイベントが4つあって
データを表示させたとき呼び込めなくなる。
Formを終了させても再発するし以前から起こっているし
どんな原因が考えられますか?
以下ソース
質問B
RichEditのカーソル行を調べるために
GetScrollPosを使っているのだけど期待する値が来ません。
i:=GetScrollPos(RichEdit1.Handle,SB_VERT);
gyo:=((i+y-5) div 17); S:=Copy(RichEdit1.lines[gyo],7,4);
3行目、4行目にカーソルがあるにもかかわらず
変数gyoには475が返ってきます。
質問Aの形式で質問されても苦労するから
質問Bみたいな質問にできませんか?って指摘しているのだけど
同じプロジェクトの人とクラスのやりとりしているそうですけど
質問Bでできるようになれば全体の開発速度も上がるよ
>私みたいな年になっても、調べたらできるんですね。
年は関係ないですよ
苦労しつつプログラム書いていれば理解できていきます
多分なんですけど(違ってたら他の人ごめんなさい)
回答してくれている人、ASさんより かなり年上かと
MZ-80とか書くと反応する人多い世代かと
思ったり思わなかったり
はい!MZ-80に反応する人です。
さらにはTK-80にも。(^^;
まぁ私も「35歳の壁」など14年も前に突破している口ですから
年齢など関係ないですよ。
おはようございます。
takeさんへ
言われてることが理解できました。
今後気を付けます。
さて、朝実行してみると、やはりエラー続出になりました。
で、ボタンBを押してデータを表示するプログラムに追加しましたが
RichEdit1.visible:=True;
RichEdit1.Lines.clear;
RichEdit1.setfocus;
RichEdit1.SelStart :=0;// カーソルを最初に移動する
// カーソル位置を表示させるようメッセージを送る
SendMessage(RichEdit1.Handle, EM_SCROLLCARET, 0 ,0);
//追加した文
i:=SetScrollPos(RichEdit1.Handle,0,0,BO);
やはり、エラーは止まりません。
ご助言をいただきたいと思います。
いらない文がありますが、苦労の後ですのでご容赦を。
また、問題点を元から立つ方法を使いたくなっていますが、
今回は急いでいませんので、ゆっくり待ちます。
よろしく、お願いします。
>エラー続出になりました。
>やはり、エラーは止まりません。
エラーメッセージは、何と表示されていますか?
また、エラーが発生するのは、ソースコードのどの行が実行されたときに発生しますか?
Delphiはそう詳しくないですがこう言う時は
再現できる最低限のソースを提示しないと多分解決しませんよ。
新規でプロジェクトを作成して再現させるか
ギリギリまでコードをコメントにして再現させるとか
まぁデバッグの基本です。
プログラムは記述したようにしか動かないので
とにかく悪いのは自分、位に考えないと。
#質問をみていると
#ステップ実行とか変数参照とか基本的なことが出来ていない
#感じがするのですがその辺は大丈夫ですか?
本当にtakeさんの仰る事を理解されたのか疑問に思うほど
透視能力が必要な質問ですが(^^;
>やはり、エラーは止まりません。
とは、何か例外が発生する(エラーメッセージウィンドウが表示される)んでしょうか?
それとも
>gyo:=((i+y-5) div 17); S:=Copy(RichEdit1.lines[gyo],7,4);
でgyoの値が期待した値にならないということでしょうか?
「エラーは止まりません」と書かれると、大抵の人は前者を想像します。
>いらない文がありますが
とは
RichEdit1.visible:=True;
RichEdit1.SelStart :=0;// カーソルを最初に移動する
これらの事でしょうか?
多少の余計な部分はあっても大した事ではないですが
ここまで書いたら肝心の「データを表示する」部分が、どこにどのように書かれているかが
重要なヒントになる可能性があります。
おそらく
RichEdit1.SelStart :=0;
の後に
RichEdit1.Lines.LoadFromFile(...
とか
RichEdit1.Lines.Add(...
とか
RichEdit1.Lines.Text := ...
とかでしょうけど。
ボタンAとボタンBではクリックイベントの内容は同じですか?
特に「データを表示する」部分ですけど。
で
i:=SetScrollPos(RichEdit1.Handle,0,0,BO);
この BO ってどこで宣言されてます?
まぁ、引数の意味から多分booleanの変数でTrueになっているのだろうと思いますが
だとすると、この文は横スクロールバーを左端に持っていくだけですので
クリックされた行の取得にはあまり関係ないかと。
全体としてやりたいことは
1.ABどちらかのボタンをクリックして、何らかの文字列をRichEditに読み込む
2.表示された文字列のある行を右クリックすると、その行だけをRichEditに再表示する
3.指定した行に空白が含まれていた場合は、最初の空白以降は表示しない
でいいでしょうか?
今までにアップされた質問内容とソースの断片から、こんな推測をしていますが
この前提でよろしいですか?
今回の質問ではOnMouseDownイベントで右クリックかどうか判断していませんが
前回の質問で右クリックにこだわっていましたので、本来は右クリックなのかと想像しましたが。
で、もし実際のソースでは右クリックの時だけに限っているのであれば
うまく動作しない可能性があります。
右クリックではカーソル位置が移動しませんので。(XE2+WinXPで確認)
上記の推測に間違いがない場合は、torさんが提示されたTRichEdit.CaretPosを使って
procedure TForm1.RichEdit1MouseDown(Sender: TObject;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
s:string;
begin
if RichEditFlg=true then //これが何なのか分かりませんが
begin
s := richedit1.Lines[richedit1.CaretPos.y];
p := pos(' ', s);
if P > 0 then s := copy(s, 1, p - 1);
richedit1.Clear;
richedit1.lines.add(s);
end
end;
これでいいのではないかと思いますが。
何をしたいのかすらしっかり書かれてない質問だね。
本人も何をしたいのか、本来の目的をあまり把握せずに質問してないか?
とりあえず、gyoに何を入れたいのか言ってみてよ。
期待する値が何で、実際に求められた値が何になったかも。
おはようございます。
igyさんへ
エラーというのは、期待しているgyoが読み込めないで400番台の数字を読み込み、空白行を読み込んで変換エラーが出ることです。
むさんへ
ステップ実行とか、確かにしたことないですね。
また、試してみます。
Questさんへ
ありがとうございました。
Torさんの
>TRichEdit.CaretPos に行番号が入っていますから、そのまま使えるはずです。
を見落として下に書かれていたHPを調べていました。
torさん、ごめんなさいです。
s := richedit1.Lines[richedit1.CaretPos.y];
これを使うと、今のところですが、まったく問題は起こりません。
かなりの確率で異常を起こすことができる操作を見出していたのですが、
それを使っても、異常は起こりません。
問題は解決と思います。
その他にも、参考になるご指摘も受け、疑問が1つ解決しました。
ありがとうございました。
あさんへ
gyoには、mousedownした場所の行数が入ります。
4行目をクリックしたら、400番台の数字が入ってしまう場合があるんです。
最後にもう一つ質問させてください。今回の問題は下の理由で起こりました。
RichEdit1.SetFocus;
SendMessage(RichEdit1.Handle, EM_SCROLLCARET, 0 ,0);
これで、スクロールバーが移動したのですが、
初期位置に戻すために
RichEdit1.visible:=True;
RichEdit1.Lines.clear;
RichEdit1.SelStart :=0;// カーソルを最初に移動する
// カーソル位置を表示させるようメッセージを送る
SendMessage(RichEdit1.Handle, EM_SCROLLCARET, 0 ,0);
を使いました。
これでは、スクロールバーの位置scrollposを0にできないんですか?
i:=SetScrollPos(RichEdit1.Handle,0,0,BO);
以外で、0にする方法を教えてくださいませんか。
よろしく、お願いします。
>エラーというのは、期待しているgyoが読み込めないで400番台の数字を読み込み、空白行を読み込んで変換エラーが出ることです。
“エラー”の一言だけだと、他の回答者はわからないので、質問時に上記のようにをきちんと書きましょう。
繰り返しになりますが、
技術系メーリングリストで質問するときのパターン・ランゲージ
http://www.hyuki.com/writing/techask.html
が参考になるかと思います。
>エラーというのは、期待しているgyoが読み込めないで400番台の数字を読み込み、空白行を読み込んで変換エラーが出ることです。
さらに、2012/10/06(土) 11:57:12で挙げているコードには、その“期待しているgyoが読み込めない”部分が挙げられていません。
コードを挙げる場合、エラーが出るというのであれば、該当箇所のコードも書きましょう。
次から質問は、とりあえずこんな感じで書いてくれ。
本当に要点だけ書いとくから。これくらいなら分かるよな?
1 環境
Win 7 Pro + Delphi XE
2 したいこと
TRichEditで、マウスでクリックした行の行番号を取得したい。
3 問題点
マウス位置の行番号を取得するために、次のようなコードを記述した。
Gyo := 〜
しかし、〜行目をクリックすると、行番号が400と出てしまう。
これを4と求められるようにしたい。
あんたの場合、こんな書き方になってるから。
1 記載なし
2 記載なし
3 Gyo := 〜
この行がエラーを起こします。なぜですか?
>むさんへ
>ステップ実行とか、確かにしたことないですね。
>また、試してみます。
いやいや、ここはさらっと流す所じゃなくてソレできないと
効率悪いでしょ。適度な所にブレークポイント入れてステップ実行
して変数の値を確認するのが基本ですけど、もしかして独学ですか?
#確かに毎回実行して結果をみるのもデバッグですけど・・・
#そういうレベルなら本買いまくって読んだ方がいいですよ
む さんへ
.. 上略 ...
>して変数の値を確認するのが基本ですけど、もしかして独学ですか?
.. 下略 ...
独学で,Delphiを使ってはいけないのですか?。
む さんへ
一部訂正..
>.. 上略 ...
>して変数の値を確認するのが基本ですけど、もしかして独学ですか?
>.. 下略 ...
>独学で,Delphiを使ってはいけないのですか?。
独学では、何か不都合が有りますか?。
独学で尚かつ一人で、中堅企業の基幹システムを構築して問題なく稼働していますが。
横から飛び入り さんへ
その横から入りますが私も独学です
Delphi はデビューした頃からそんな初心者でも入りやすいイメージがありましたしポインタにくじけた人、VB の挙動などに泣かされてらやってきた人も多いですし D6 の様にフリー環境もありましたので独学の方は結構おられると思います
む さんは自分の思い込みだけで進んできたようなイメージで「独学」って書かれていますが要は
・疑問があったら調べようよ
・入門書も読んでいないの?
ということが言いたいのだと思いますよ
おそらく何度も「ステップ実行」とか「ブレークポイント」とかいうキーワードが出ていても AS さんはまだ試していないというか調べてもいないと思います
AS さんへ、
エラーの起こるところや、期待値が入っていない変数のあるあたりの行(←これは Delphi のプログラムコードの行です)で F5 を押せば「ブレークポイント」が設定されます(右クリックから細かい設定も出来ます)
そして、「F9」を押せば「ブレークポイント」を通った時にそこで止まりますので今度は「F8」を押して一行ずつ実行させてみてください
「F7」なら他の関数に飛んでもステップ実行となります
そこで gyo なり気になる変数を選択して「ctrl + F7」で内容が出ます
監視表示することも出来ます
>これでは、スクロールバーの位置scrollposを0にできないんですか?
> i:=SetScrollPos(RichEdit1.Handle,0,0,BO);
>以外で、0にする方法を教えてくださいませんか。
えーと、回答をすべて読まれていらっしゃるのでしょうか?
前回書きましたが、SetScrollPos関数の第2引数を0にすると
横スクロールバーが対象になります。
行方向つまり縦スクロールなら
i:=SetScrollPos(RichEdit1.Handle,SB_VERT,0,BO);
ですね。
さらに、この関数の戻り値は
http://msdn.microsoft.com/ja-jp/library/cc411085.aspx
ここによると
>関数が成功すると、スクロールボックスのそれまでの位置が返ります。
とありますので、この関数を実行する前の位置が返ります。
つまりスクロールバーが左端(上下なら上端)にない場合は
0以外の値が返ることになります。
また、実験してみると(見かけ上の)スクロールバーの位置と
返ってくる値にズレがあるようです。
この関数を呼んだだけでは、スクロールバーは移動しますが
カーソル位置は変化しません。
SetScrollPos関数を呼んでスクロールバーが先頭に移動した後
さらにスクロールバーの左端(あるいは上端)の三角マークボタンをクリックすると
動かないはずのスクロールバーが先ほどの位置辺りへ移動します。
この動作から、スクロールバーの表示はマウスによる操作の際に
カーソル位置から再計算されるのではないかと思われますが
何か不可解な動作をします。(詳しく調査すれば分かりそうだが無意味なのでパス)
いずれにしても、この関数は移動前の位置を返しますので
現在のスクロールバーの位置を調べるには不適切でしょう。
では、どうすればいいかという事ですが、上記のサイトの上のほうに
>注意 SetScrollPos 関数は、下位互換性の目的で提供されています。新しいアプリケーションは、代わりに SetScrollInfo 関数を使うべきです。
とありますので、SetScrollInfoを使えばいいでしょう。
具体的には
var
ScrollInfo: TScrollInfo;
begin
ScrollInfo.cbSize := SizeOf(ScrollInfo);
ScrollInfo.fMask := SIF_POS;
ScrollInfo.nPos := 0; //新しい位置
SetScrollInfo(RichEdit1.Handle, SB_VERT, ScrollInfo, True);
end;
とすれば、スクロールバーの位置を0にできます。
おっと、本来は現在の位置を取得するのでしたね
var
ScrollInfo: TScrollInfo;
p: integer;
begin
ScrollInfo.cbSize := SizeOf(ScrollInfo);
ScrollInfo.fMask := SIF_POS;
GetScrollInfo(RichEdit1.Handle, SB_VERT, ScrollInfo);
p := ScrollInfo.nPos;
end;
とすれば、pに現在のスクロールバーの位置が返ります。
が、TRichEdit.CaretPosで大元の目的を達成されているので
今後このスレッドを見た人に、なんらかのヒントになればと。
ちなみに、SetScrollPosについての情報はグーグル先生に聞きました。
あぁ、こう書くと分からない人もいるかもしれないので(^^;)
グーグルでSetScrollPosを検索したら一番最初にでてきました。
第2引数を0にすると横スクロールになるというのは
SetScrollPos関数のページに出てきたSB_CTL、SB_HORZ、SB_VERTを
さらにグーグルで検索したら0がSB_HORZであることが分かりました。
GetScrollInfoのDelphiでの使い(書き)方については
(少々の)C言語の知識と(ある程度の)Delphiでの経験値が必要でしたが。
今晩は。
書き込みありがとうございました。
皆さんへ
独学については、プロの時のアッセンブラ以外は、BAS3もN88BASICも、パスカル、FBASIC、C++、VBそしてdelphiも独学です。
C++は全くものになりませんでしたが。
「初めてのdelphi」とかいう本を読んで勉強しました。
私のXE2は、エラーが起こって停止した後ブレークを押しても問題個所に移動しないんで、非常に苦労してます。
移動させる方法があったら教えてください。
ステップ実行の代わりにshowmessage();を使ってやってます。
あさんへ
1,2については全くなかったですね。
XE2と64ビットPCとwin7です。
けどさんへ
そういう使い方は知りませんでした。
ありがとうございました。
Questさんへ
今日もありがとうごました。
読み落としについては、すみません。
言葉で書くより、ちゃんとしたコードで書いてもらうほうが分かりますね。
私もこれから書くときはコードを使って、話をするようにしないといけませんね。
>GetScrollInfoのDelphiでの使い(書き)方については(少々の)C言語の知識と(ある程度の)Delphiでの経験値が必要でしたが。
私も読んではみましたが、C言語の知識が足りなくて、使用できませんでした。
本当にありがとうございました。
これで、次の問題に移れます。
問題点が整理できて解決できない場合はまた来ますので、よろしくです。
ツイート | ![]() |