none
SetCaretPosでキャレットを設定しても、入力時に元の場所に戻ってしまう。 RRS feed

  • 質問

  • 現在VBAのコーディングの高速化のためにVBEのcomアドインを作っています。

    「現在の行をコメントにする」というものをとりあえず作りました。

    ところがReplaceLineメソッドで行を変更するとキャレットの位置が下にずれてしまいます。

    なのでキャレットの位置を元に戻すためにGetCaretPosのあとにReplaceLineメソッドを実行し、

    その後SetCaretPosを呼び出せばキャレットの位置を復元出来ると思いましたが

    見かけのキャレットの位置は同じままなのですが、文字を入力すると元の場所(下の行)へ文字が入ってしまいました。

    VBEのキャレット(入力)位置を制御したいのですがどのようにすればよいでしょうか?ぜひご教示お願いします。

    Option Compare Binary
    Option Explicit
        
    Private Type POINT
        X As Long
        Y As Long
    End Type
    
    Private Declare Function GetCaretPos Lib "user32" ( _
                    ByRef lpPoint As POINT) As Long
                    
    Private Declare Function SetCaretPos Lib "user32" ( _
                    ByVal X As Long, _
                    ByVal Y As Long) As Long
    
    Private pVBE  As VBE
    Private WithEvents Addin As CommandBarButton
    
    Private Sct(3) As Long
    Private pPoint As POINT
    Private nCode As String
    
    Private Sub AddinInstance_OnConnection( _
                    ByVal Application As Object, _
                    ByVal ConnectMode As AddInDesignerObjects.ext_ConnectMode, _
                    ByVal AddInInst As Object, _
                    custom() As Variant)
        
        Set pVBE = Application
        'アドインボタン追加
        Set Addin = pVBE.CommandBars("メニュー バー").Controls.Add(msoControlButton)
        
        With Addin
            'ショートカットキー等設定する
            .Caption = "Quick(&S)"
            .Style = msoButtonCaption
        End With
    End Sub
    
    Private Sub Addin_Click( _
                    ByVal Ctrl As Office.CommandBarButton, _
                    CancelDefault As Boolean)
        With pVBE.ActiveCodePane
            '現在の入力行を取得
            .GetSelection Sct(0), Sct(1), Sct(2), Sct(3)
            
            With .CodeModule
                '現在の行の内容取得
                nCode = .Lines(Sct(0), 1)
                '先頭にシングルクォート追加
                nCode = "'" & nCode
                
                'キャレット位置取得
                GetCaretPos pPoint
                '行を置換する
                .ReplaceLine Sct(0), nCode
                'キャレット位置復元
                SetCaretPos pPoint.X, pPoint.Y
            End With
        End With
    End Sub
    

    2012年7月27日 15:00

回答

  • きちんと実験していないので推測になりますが、キャレット位置の管理が独自に実装されているのではないでしょうか。
    せっかくなので、GetSelection と対になる SetSelection を使ってみては?GetSelection であらかじめ現在位置を得ているようですし。

    (もし、試した後でうまくいっていなかったのであればごめんなさい)

    文字が入るのはカーソル位置ではないでしょうか?、カーソルを移動してから、キャレットを移動させたと思います。キャレット位置だけで十分なのでしょうか?

    文字の入力位置を表す言葉は キャレット です。カーソルを移動するというのは何を意図されているかわかりませんが、「文字入力位置を表すカーソル」のつもりであれば、「キャレット」と同義と言えます。

    キャレットと書かず、カーソルと書く文献・分野もあると思いますが、どちらも同じものだと、私はとらえています。(少なくとも文字入力位置を表す場合において)

    • 編集済み AzuleanMVP 2012年7月28日 3:09
    • 回答としてマーク sskr 2012年7月28日 13:55
    2012年7月28日 3:08

すべての返信

  • Fuda1です。

    文字が入るのはカーソル位置ではないでしょうか?、カーソルを移動してから、キャレットを移動させたと思います。キャレット位置だけで十分なのでしょうか?イメージとして、SetConsoleCursorPosition http://msdn.microsoft.com/ja-jp/library/cc429740.aspxこんな事ができれば良いのかなぁと思ってます。VBEが、コンソールと同じか試さないと行けないのですが、今、別件で急いでますので、後でテストして見ます。

    Win32API コンソールスクリーンバッファのカーソル位置を設定する
    http://d.hatena.ne.jp/s-kita/20100926/1285470932
    2012年7月28日 1:19
  • きちんと実験していないので推測になりますが、キャレット位置の管理が独自に実装されているのではないでしょうか。
    せっかくなので、GetSelection と対になる SetSelection を使ってみては?GetSelection であらかじめ現在位置を得ているようですし。

    (もし、試した後でうまくいっていなかったのであればごめんなさい)

    文字が入るのはカーソル位置ではないでしょうか?、カーソルを移動してから、キャレットを移動させたと思います。キャレット位置だけで十分なのでしょうか?

    文字の入力位置を表す言葉は キャレット です。カーソルを移動するというのは何を意図されているかわかりませんが、「文字入力位置を表すカーソル」のつもりであれば、「キャレット」と同義と言えます。

    キャレットと書かず、カーソルと書く文献・分野もあると思いますが、どちらも同じものだと、私はとらえています。(少なくとも文字入力位置を表す場合において)

    • 編集済み AzuleanMVP 2012年7月28日 3:09
    • 回答としてマーク sskr 2012年7月28日 13:55
    2012年7月28日 3:08
  • Fuda1様、Azulean様、ご返事いただきありがとうございます。

    Azulean様のご回答である「SetSelection」を使うことで、今回の問題は解決しました。

    自分で「GetSelection」を使っていながら、「キャレットの制御」という観点から「SetSelection」を使うとは

    思ってもいませんでしたので「言われてみれば…」という感じがして少し恥ずかしく思います。

    Azulean様の回答を「回答としてマーク」させて頂きます。

    返事をくださったお二方に重ねてお礼申し上げます。またよろしくお願いします。sskr

    差分のコード

    Private Sub Addin_Click( _
                    ByVal Ctrl As Office.CommandBarButton, _
                    CancelDefault As Boolean)
        With pVBE.ActiveCodePane
            '現在の入力行を取得
            .GetSelection Sct(0), Sct(1), Sct(2), Sct(3)
            
            With .CodeModule
                '現在の行の内容取得
                nCode = .Lines(Sct(0), 1)
                '先頭にシングルクォート追加
                nCode = "'" & nCode
                
                '行を置換する
                .ReplaceLine Sct(0), nCode
            End With
            'キャレット位置を復元
            .SetSelection Sct(0), Sct(1), Sct(2), Sct(3)
        End With
    End Sub
    

    2012年7月28日 13:54