Solved

Change RichTextBox Cursor Appearance

Posted on 2002-04-25
5
847 Views
Last Modified: 2007-12-19
How can I change the appearance of a RichTextBox's cursor between the usual blinking bar and a blinking blob highlighting the following character.

As you might expect, I'll be using this technique for a visual representation of whether the keyboard is in insert mode or overwrite mode.  This question is not about how to detect whether the keyboard is in insert mode or overwrite mode.
0
Comment
Question by:SimonORorke
  • 2
  • 2
5 Comments
 
LVL 44

Accepted Solution

by:
bruintje earned 200 total points
ID: 6970466
Hi simonORorke,

You can call a couple of APIs to create and destroy your own caret

a complete sample on how to use it
http://www.vb-world.net/misc/caret/index2.html

HTH:O)Bruintje
0
 
LVL 49

Expert Comment

by:Ryan Chong
ID: 6970470
Research of its SelStart and SelLength Property..
0
 

Author Comment

by:SimonORorke
ID: 6974440
Thanks Bruintje.  I would never have guessed that the thing was called a caret!  So you have pointed me in the right direction.  But to make carets work with a RichTextBox, there turns out to be a lot more too it than is explained in the link you gave me or indeed in any of the other caret examples I could find.  So I can only give you a B.  If you look at the following sample program that I have just written, you will see why.  In the sample program I have not even shown how to toggling the caret on and off in step with changes in the keyboard state between overwrite mode and insert mode:  I've just started looking into that and it is clear that it will make the logic quite a bit more complex than it already is.

On a Form, place a RichTextBox and insert the following code.

Option Explicit
Private Declare Function CreateCaret Lib "User32" ( _
  ByVal hWnd As Long, _
  ByVal hBitmap As Long, _
  ByVal nWidth As Long, _
  ByVal nHeight As Long) As Long
Private Declare Function DestroyCaret Lib "User32" () As Long
Private Declare Function GetFocus Lib "User32" () As Long
Private Declare Function GetForegroundWindow Lib "User32" () As Long
Private Declare Function ShowCaret Lib "User32" ( _
  ByVal hWnd As Long) As Long

Private Sub Form_Load()
' Using a proportional-pitch font will be a good test of
' whether we will be able to correctly make the caret the
' same size as the character at which the cursor is positioned.
RichTextBox1.Font.Name = "Verdana"
' See comment in Timer1_Timer.
Timer1.Interval = 10
End Sub

Private Sub Form_Unload(Cancel As Integer)
Dim Result As Long
Result = DestroyCaret
End Sub

Private Sub RichTextBox1_GotFocus()
SetCursorShape
End Sub

Private Sub SetCursorShape()
' Set the RichTextBox's cursor to a caret if no text
' is selected.
'
' It would be nice to make the caret a different colour than
' what is used to indicate the selected text in the RichTextBox.
' That would require the hBitmap parameter of CreateCaret
' to be set to a picture of
' data type IPictureDisp (same as StdPicture), e.g. the Picture
' property of a Picture control.
' But we are going to use the nWidth and nHeight properties
' of CreateCaret to specify the size of the caret and
' nWidth and nHeight get ignored if hBitmap is specified.
' So, to get the caret both the right size and the right colour in
' an application where the size of the characters might vary,
' for example where a proportional-pitch font is used,
' we would need to be able to draw a picture of the required colour
' and size programatically and convert it to an IPictureDisp.
' I do not know how to do that.
' If the size of characters is not expected to vary,
' i.e. when the same fixed-pitch font will always be used and
' without using features such as bold, which might affect charater width,
' then the hBitmap parameter of CreateCaret could be set to
' a predefined picture of the right size and colour.
Dim Result As Long
Dim NextChar As String
If RichTextBox1.SelLength = 0 Then
  ' This method of calculating the required height and
  ' with of the caret will works irrespective of whether a fixed-pitch font
  ' or a proportional-pitch font is being used.
  ' Make the height and width of the caret the same as the height
  ' and width of the character at which
  ' the cursor is positioned, if any:
  ' temorarily select the character to
  ' find out what it is.
  RichTextBox1.SelLength = 1
  NextChar = RichTextBox1.SelText
  RichTextBox1.SelLength = 0
  ' Allow Me.TextWidth and Me.TextHeight to be used to calculate the
  ' width and height required for the caret.
  Me.Font = RichTextBox1.Font
  If NextChar <> "" Then
    Result = CreateCaret( _
      hWnd:=RichTextBox1.hWnd, _
      hBitmap:=0, _
      nWidth:=Me.ScaleX(Me.TextWidth(NextChar), Me.ScaleMode, vbPixels), _
      nHeight:=Me.ScaleY(Me.TextHeight(NextChar), Me.ScaleMode, vbPixels))
  Else
    ' The cursor is not positioned at a character (e.g. it might
    ' be at the end of a line), so make the caret as big as one of the
    ' largest letters in the font.
    Result = CreateCaret( _
      hWnd:=RichTextBox1.hWnd, _
      hBitmap:=0, _
      nWidth:=Me.ScaleX(Me.TextWidth("H"), Me.ScaleMode, vbPixels), _
      nHeight:=Me.ScaleY(Me.TextHeight("H"), Me.ScaleMode, vbPixels))
  End If
  Result = ShowCaret(RichTextBox1.hWnd)
End If
End Sub

Private Sub RichTextBox1_KeyDown(KeyCode As Integer, Shift As Integer)
' See comment in Timer2_Timer.
Timer2.Interval = 1
End Sub

Private Sub RichTextBox1_MouseDown(Button As Integer, Shift As Integer, x As Single, y As Single)
' See comment in Timer2_Timer.
Timer2.Interval = 1
End Sub

Private Sub Timer1_Timer()
' The caret will get lost if the window containing the
' RichTextBox goes into background.  So we need to
' restore the caret if the window containing the
' RichTextBox comes back into foreground and the
' RichTextBox is in focus and
' and no text is selected in the RichTextBox.
Static WindowIsInForeground As Boolean
If GetForegroundWindow = Me.hWnd Then
  If Not WindowIsInForeground Then
    ' Window has just changed from background to foreground
    WindowIsInForeground = True
    If GetFocus = RichTextBox1.hWnd Then
      SetCursorShape
    End If
  End If
Else ' GetForegroundWindow <> Me.hWnd
  WindowIsInForeground = False
End If
End Sub

Private Sub Timer2_Timer()
' Unlike with TexBoxes, with RichTextBoxes,
' the caret gets destroyed whenever the user changes the position
' of the cursor with the mouse or keyboard.  So when that happens,
' we need to restore the caret.  It is no use calling SetCursorShape,
' which creates the caret, directly from the KeyDown and MouseDown
' event procedures of the RichTextBox, because evidently the caret
' gets destroyed after those event procedures have been executed.
' To get round that, the caret is restored in this Timer procedure,
' which is triggered from the KeyDown and MouseDown event
' procedures and run once, thus ensuring that the caret is restored
' after it has been destroyed.
SetCursorShape
Timer2.Interval = 0
End Sub
0
 

Author Comment

by:SimonORorke
ID: 6974450
I should have mentioned that on the Form in the sample program in my previous comment you also need to place two Timers.
0
 
LVL 44

Expert Comment

by:bruintje
ID: 6974500
Hi Simon,

that looks indeed like a lot more work then i initially thought it would be, and i didn't knew that last part on the destruction of the caret in richtext boxes, one learns something new every day

Brian
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Windows 10 start screen issues 9 51
JSON Response and request in VB6 application 11 250
message box in access 4 41
vb6 - Transfer from MSHFlexgrid1 to xls issue 8 47
I was working on a PowerPoint add-in the other day and a client asked me "can you implement a feature which processes a chart when it's pasted into a slide from another deck?". It got me wondering how to hook into built-in ribbon events in Office.
This article describes some techniques which will make your VBA or Visual Basic Classic code easier to understand and maintain, whether by you, your replacement, or another Experts-Exchange expert.
As developers, we are not limited to the functions provided by the VBA language. In addition, we can call the functions that are part of the Windows operating system. These functions are part of the Windows API (Application Programming Interface). U…
Get people started with the process of using Access VBA to control Outlook using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Microsoft Outlook. Using automation, an Access applic…

920 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now