canvas

This is an full codes example on how to draw graphics with an image's canvas. The following picture shows the effect of the running program. If you want to run this code example, just save the form's text to "FormMain.dfm", save the .h file codes to "graphwin.h" and save the .cpp file code to "graphwin.cpp", then create a new project and include these files to your project.

 DrawGraphics.png

//FormMain's text--FormMain

object FormMain: TFormMain
  Left = 250
  Top = 148
  Width = 463
  Height = 453
  Caption = 'Graphic Example'
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Default'
  Font.Style = []
  Menu = MainMenu1
  OldCreateOrder = False
  Position = poScreenCenter
  PixelsPerInch = 96
  TextHeight = 13
  object Panel1: TPanel
    Left = 0
    Top = 0
    Width = 447
    Height = 41
    Align = alTop
    TabOrder = 0
    object LineButton: TSpeedButton
      Left = 8
      Top = 8
      Width = 25
      Height = 25
      GroupIndex = 1
      Down = True
      Glyph.Data = {
        66010000424D6601000000000000760000002800000014000000140000000100
        040000000000F000000000000000000000001000000000000000000000000000
        80000080000000808000800000008000800080800000C0C0C000808080000000
        FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF00333333333333
        3333333300003333333333333333300300003333333333333333003300003333
        3333333333300333000033333333333333003333000033333333333330033333
        0000333333333333003333330000333333333330033333330000333333333300
        3333333300003333333330033333333300003333333300333333333300003333
        3330033333333333000033333300333333333333000033333003333333333333
        0000333300333333333333330000333003333333333333330000330033333333
        3333333300003003333333333333333300003033333333333333333300003333
        33333333333333330000}
      OnClick = LineButtonClick
    end
    object RectangleButton: TSpeedButton
      Left = 40
      Top = 8
      Width = 25
      Height = 25
      GroupIndex = 1
      Glyph.Data = {
        66010000424D6601000000000000760000002800000014000000140000000100
        040000000000F000000000000000000000001000000000000000000000000000
        BF0000BF000000BFBF00BF000000BF00BF00BFBF0000C0C0C000808080000000
        FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF00333333333333
        3333333300003000000000000000000300003033333333333333330300003033
        3333333333333303000030333333333333333303000030333333333333333303
        0000303333333333333333030000303333333333333333030000303333333333
        3333330300003033333333333333330300003033333333333333330300003033
        3333333333333303000030333333333333333303000030333333333333333303
        0000303333333333333333030000303333333333333333030000303333333333
        3333330300003033333333333333330300003000000000000000000300003333
        33333333333333330000}
      OnClick = RectangleButtonClick
    end
    object EllipseButton: TSpeedButton
      Left = 72
      Top = 8
      Width = 25
      Height = 25
      GroupIndex = 1
      Glyph.Data = {
        4E010000424D4E01000000000000760000002800000012000000120000000100
        040000000000D800000000000000000000001000000000000000000000000000
        80000080000000808000800000008000800080800000C0C0C000808080000000
        FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF00333333000000
        3333330000003333003333330033330000003330333333333303330000003303
        3333333333303300000030333333333333330300000030333333333333330300
        0000033333333333333330000000033333333333333330000000033333333333
        3333300000000333333333333333300000000333333333333333300000000333
        3333333333333000000030333333333333330300000030333333333333330300
        0000330333333333333033000000333033333333330333000000333300333333
        003333000000333333000000333333000000}
      OnClick = EllipseButtonClick
    end
    object RoundRectButton: TSpeedButton
      Left = 104
      Top = 8
      Width = 25
      Height = 25
      GroupIndex = 1
      Glyph.Data = {
        4E010000424D4E01000000000000760000002800000012000000120000000100
        040000000000D800000000000000000000001000000000000000000000000000
        80000080000000808000800000008000800080800000C0C0C000808080000000
        FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF00333300000000
        0033330000003300333333333300330000003033333333333333030000003033
        3333333333330300000003333333333333333000000003333333333333333000
        0000033333333333333330000000033333333333333330000000033333333333
        3333300000000333333333333333300000000333333333333333300000000333
        3333333333333000000003333333333333333000000003333333333333333000
        0000303333333333333303000000303333333333333303000000330033333333
        330033000000333300000000003333000000}
      OnClick = RoundRectButtonClick
    end
    object PenButton: TSpeedButton
      Left = 176
      Top = 8
      Width = 25
      Height = 25
      AllowAllUp = True
      GroupIndex = 2
      Glyph.Data = {
        66010000424D6601000000000000760000002800000015000000140000000100
        040000000000F000000000000000000000001000000000000000000000000000
        80000080000000808000800000008000800080800000C0C0C000808080000000
        FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF00333333333333
        3333333339003333333333333333003334003333333333333330F00334003333
        33333333330F0003300033333333333330F00033300033333333333300000333
        3C00333333333330F0003333380033333333330F0003333330003333333330F0
        003333333700333333330F0003333333370033333330F000333333333F003333
        330F0003333333333700333330F00033333333333F0033330F00033333333333
        37003330F0003333333333333700333000033333333333333000330F00333333
        3333333337003300333333333333333337003033333333333333333337003333
        33333333333333333700}
      OnClick = PenButtonClick
    end
    object BrushButton: TSpeedButton
      Left = 208
      Top = 8
      Width = 25
      Height = 25
      AllowAllUp = True
      GroupIndex = 3
      Glyph.Data = {
        66010000424D6601000000000000760000002800000013000000140000000100
        040000000000F000000000000000000000001000000000000000000000000000
        80000080000000808000800000008000800080800000C0C0C000808080000000
        FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF00333333333333
        3333333F000030030000003333333337000033333330F0003333333B00003333
        33330F000333333000003333333330F00033333700003333333330F000333330
        00003333333300F00003333A0000333333300FF0000333370000333333300F00
        00033337000033333300FF000000333E00003333330FF0000000333700003333
        330FF00000003337000033333300F0000000333F000033333330000000033337
        0000333333330FFF003333370000333333330FFF0033333F0000333333330FFF
        0033333E0000333333330FFF0033333700003333333330000333333F00003333
        33333333333333300000}
      OnClick = BrushButtonClick
    end
  end
  object PenBar: TPanel
    Left = 0
    Top = 41
    Width = 447
    Height = 41
    Align = alTop
    TabOrder = 1
    Visible = False
    object SolidPen: TSpeedButton
      Left = 8
      Top = 8
      Width = 25
      Height = 25
      GroupIndex = 4
      Down = True
      Glyph.Data = {
        B2000000424DB200000000000000760000002800000015000000050000000100
        0400000000003C00000000000000000000001000000000000000000000000000
        BF0000BF000000BFBF00BF000000BF00BF00BFBF0000C0C0C000808080000000
        FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF00333333333333
        333333333700333333333333333333333000300000000000000000003F003333
        33333333333333333000333333333333333333333000}
      OnClick = SetPenStyle
    end
    object DashPen: TSpeedButton
      Left = 33
      Top = 8
      Width = 25
      Height = 25
      GroupIndex = 4
      Glyph.Data = {
        B2000000424DB200000000000000760000002800000015000000050000000100
        0400000000003C00000000000000000000001000000000000000000000000000
        BF0000BF000000BFBF00BF000000BF00BF00BFBF0000C0C0C000808080000000
        FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF00333333333333
        333333333700333333333333333333333000300000300000030000033F003333
        33333333333333333000333333333333333333333000}
      OnClick = SetPenStyle
    end
    object DotPen: TSpeedButton
      Left = 58
      Top = 8
      Width = 25
      Height = 25
      GroupIndex = 4
      Glyph.Data = {
        B2000000424DB200000000000000760000002800000015000000050000000100
        0400000000003C00000000000000000000001000000000000000000000000000
        80000080000000808000800000008000800080800000C0C0C000808080000000
        FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF00333333333333
        3333333333003333333333333333333333003030303030303030303033003333
        33333333333333333300333333333333333333333300}
      OnClick = SetPenStyle
    end
    object DashDotPen: TSpeedButton
      Left = 83
      Top = 8
      Width = 25
      Height = 25
      GroupIndex = 4
      Glyph.Data = {
        B2000000424DB200000000000000760000002800000015000000050000000100
        0400000000003C00000000000000000000001000000000000000000000000000
        80000080000000808000800000008000800080800000C0C0C000808080000000
        FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF00333333333333
        3333333330003333333333333333333330003000003030000030300030003333
        33333333333333333F00333333333333333333333700}
      OnClick = SetPenStyle
    end
    object DashDotDotPen: TSpeedButton
      Left = 108
      Top = 8
      Width = 25
      Height = 25
      GroupIndex = 4
      Glyph.Data = {
        B2000000424DB200000000000000760000002800000015000000050000000100
        0400000000003C00000000000000000000001000000000000000000000000000
        80000080000000808000800000008000800080800000C0C0C000808080000000
        FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF00333333333333
        3333333333003333333333333333333333003000003030300000303033003333
        33333333333333333300333333333333333333333300}
      OnClick = SetPenStyle
    end
    object ClearPen: TSpeedButton
      Left = 133
      Top = 8
      Width = 25
      Height = 25
      GroupIndex = 4
      Glyph.Data = {
        B2000000424DB200000000000000760000002800000015000000050000000100
        0400000000003C00000000000000000000001000000000000000000000000000
        80000080000000808000800000008000800080800000C0C0C000808080000000
        FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF00333333333333
        3333333333003333333333333333333333003FFFFFFFFFFFFFFFFFFF33003333
        33333333333333333300333333333333333333333300}
      OnClick = SetPenStyle
    end
    object PenColor: TSpeedButton
      Left = 174
      Top = 8
      Width = 25
      Height = 25
      Glyph.Data = {
        66010000424D6601000000000000760000002800000014000000140000000100
        040000000000F000000000000000000000001000000010000000000000000000
        BF0000BF000000BFBF00BF000000BF00BF00BFBF0000C0C0C000808080000000
        FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF00999BBBBFAAAA
        4CCCFFFF0000999BBBBFAAAACCCCFFFF0000999BBBBFAAAA4CCCFFFF0000999B
        BBBFAAAACCCCFFFF0000999BBBBFAAAA4CCCFFFF0000999BBBBFAAAACCCCFFFF
        0000999BBBBFAAAA4CCCFFFF0000999BBBBFAAAACCCCFFFF0000999BBBBFAAAA
        4CCCFFFF0000999BBBBFAAAACCCCFFFF0000999BBBBFAAAA4CCCFFFF0000999B
        BBBFAAAACCCCFFFF0000999BBBBFAAAA4CCCFFFF0000999BBBBFAAAACCCCFFFF
        0000999BBBBFAAAA4CCCFFFF0000999BBBBFAAAACCCCFFFF0000999BBBBFAAAA
        4CCCFFFF0000999BBBBFAAAACCCCFFFF0000999BBBBFAAAA4CCCFFFF0000999B
        BBFFAAAFFCCCFFFF0000}
      OnClick = PenColorClick
    end
    object PenSize: TEdit
      Left = 280
      Top = 12
      Width = 29
      Height = 21
      TabOrder = 1
      Text = '1'
      OnChange = PenSizeChange
    end
    object PenWidth: TUpDown
      Left = 309
      Top = 12
      Width = 12
      Height = 21
      Associate = PenSize
      ArrowKeys = False
      Min = 0
      Position = 1
      TabOrder = 0
      Wrap = False
    end
  end
  object BrushBar: TPanel
    Left = 0
    Top = 82
    Width = 447
    Height = 41
    Align = alTop
    TabOrder = 2
    Visible = False
    object SolidBrush: TSpeedButton
      Left = 8
      Top = 8
      Width = 25
      Height = 25
      GroupIndex = 1
      Down = True
      Glyph.Data = {
        66010000424D6601000000000000760000002800000014000000140000000100
        040000000000F000000000000000000000001000000000000000000000000000
        BF0000BF000000BFBF00BF000000BF00BF00BFBF0000C0C0C000808080000000
        FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF00333333333333
        3333333300003000000000000000000300003000000000000000000300003000
        0000000000000003000030000000000000000003000030000000000000000003
        0000300000000000000000030000300000000000000000030000300000000000
        0000000300003000000000000000000300003000000000000000000300003000
        0000000000000003000030000000000000000003000030000000000000000003
        0000300000000000000000030000300000000000000000030000300000000000
        0000000300003000000000000000000300003000000000000000000300003333
        33333333333333330000}
      OnClick = SetBrushStyle
    end
    object ClearBrush: TSpeedButton
      Left = 40
      Top = 8
      Width = 25
      Height = 25
      GroupIndex = 1
      Glyph.Data = {
        66010000424D6601000000000000760000002800000014000000140000000100
        040000000000F000000000000000000000001000000000000000000000000000
        BF0000BF000000BFBF00BF000000BF00BF00BFBF0000C0C0C000808080000000
        FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF00333333333333
        3333333300003000000000000000000300003033333333333333330300003033
        3333333333333303000030333333333333333303000030333333333333333303
        0000303333333333333333030000303333333333333333030000303333333333
        3333330300003033333333333333330300003033333333333333330300003033
        3333333333333303000030333333333333333303000030333333333333333303
        0000303333333333333333030000303333333333333333030000303333333333
        3333330300003033333333333333330300003000000000000000000300003333
        33333333333333330000}
      OnClick = SetBrushStyle
    end
    object HorizontalBrush: TSpeedButton
      Left = 72
      Top = 8
      Width = 25
      Height = 25
      GroupIndex = 1
      Glyph.Data = {
        66010000424D6601000000000000760000002800000014000000140000000100
        040000000000F000000000000000000000001000000000000000000000000000
        BF0000BF000000BFBF00BF000000BF00BF00BFBF0000C0C0C000808080000000
        FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF00333333333333
        3333333300003000000000000000000300003033033033033033030300003033
        0330330330330303000030330330330330330303000030330330330330330303
        0000303303303303303303030000303303303303303303030000303303303303
        3033030300003033033033033033030300003033033033033033030300003033
        0330330330330303000030330330330330330303000030330330330330330303
        0000303303303303303303030000303303303303303303030000303303303303
        3033030300003033033033033033030300003000000000000000000300003333
        33333333333333330000}
      OnClick = SetBrushStyle
    end
    object VerticalBrush: TSpeedButton
      Left = 104
      Top = 8
      Width = 25
      Height = 25
      GroupIndex = 1
      Glyph.Data = {
        66010000424D6601000000000000760000002800000014000000140000000100
        040000000000F000000000000000000000001000000000000000000000000000
        BF0000BF000000BFBF00BF000000BF00BF00BFBF0000C0C0C000808080000000
        FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF00333333333333
        3333333300003000000000000000000300003033333333333333330300003000
        0000000000000003000030333333333333333303000030333333333333333303
        0000300000000000000000030000303333333333333333030000303333333333
        3333330300003000000000000000000300003033333333333333330300003033
        3333333333333303000030000000000000000003000030333333333333333303
        0000303333333333333333030000300000000000000000030000303333333333
        3333330300003033333333333333330300003000000000000000000300003333
        33333333333333330000}
      OnClick = SetBrushStyle
    end
    object FDiagonalBrush: TSpeedButton
      Left = 136
      Top = 8
      Width = 25
      Height = 25
      GroupIndex = 1
      Glyph.Data = {
        66010000424D6601000000000000760000002800000014000000140000000100
        040000000000F000000000000000000000001000000000000000000000000000
        BF0000BF000000BFBF00BF000000BF00BF00BFBF0000C0C0C000808080000000
        FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF00333333333333
        3333333300003000000000000000000300003033303330333033300300003033
        0333033303330303000030303330333033303303000030033303330333033303
        0000303330333033303330030000303303330333033303030000303033303330
        3330330300003003330333033303330300003033303330333033300300003033
        0333033303330303000030303330333033303303000030033303330333033303
        0000303330333033303330030000303303330333033303030000303033303330
        3330330300003003330333033303330300003000000000000000000300003333
        33333333333333330000}
      OnClick = SetBrushStyle
    end
    object BDiagonalBrush: TSpeedButton
      Left = 168
      Top = 8
      Width = 25
      Height = 25
      GroupIndex = 1
      Glyph.Data = {
        66010000424D6601000000000000760000002800000014000000140000000100
        040000000000F000000000000000000000001000000000000000000000000000
        BF0000BF000000BFBF00BF000000BF00BF00BFBF0000C0C0C000808080000000
        FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF00333333333333
        3333333300003000000000000000000300003003330333033303330300003030
        3330333033303303000030330333033303330303000030333033303330333003
        0000300333033303330333030000303033303330333033030000303303330333
        0333030300003033303330333033300300003003330333033303330300003030
        3330333033303303000030330333033303330303000030333033303330333003
        0000300333033303330333030000303033303330333033030000303303330333
        0333030300003033303330333033300300003000000000000000000300003333
        33333333333333330000}
      OnClick = SetBrushStyle
    end
    object CrossBrush: TSpeedButton
      Left = 200
      Top = 8
      Width = 25
      Height = 25
      GroupIndex = 1
      Glyph.Data = {
        66010000424D6601000000000000760000002800000014000000140000000100
        040000000000F000000000000000000000001000000000000000000000000000
        BF0000BF000000BFBF00BF000000BF00BF00BFBF0000C0C0C000808080000000
        FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF00333333333333
        3333333300003000000000000000000300003033033033033033030300003000
        0000000000000003000030330330330330330303000030330330330330330303
        0000300000000000000000030000303303303303303303030000303303303303
        3033030300003000000000000000000300003033033033033033030300003033
        0330330330330303000030000000000000000003000030330330330330330303
        0000303303303303303303030000300000000000000000030000303303303303
        3033030300003033033033033033030300003000000000000000000300003333
        33333333333333330000}
      OnClick = SetBrushStyle
    end
    object DiagCrossBrush: TSpeedButton
      Left = 232
      Top = 8
      Width = 25
      Height = 25
      GroupIndex = 1
      Glyph.Data = {
        66010000424D6601000000000000760000002800000014000000140000000100
        040000000000F000000000000000000000001000000000000000000000000000
        BF0000BF000000BFBF00BF000000BF00BF00BFBF0000C0C0C000808080000000
        FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF00333333333333
        3333333300003000000000000000000300003033303330333033300300003003
        0303030303030303000030303330333033303303000030030303030303030303
        0000303330333033303330030000300303030303030303030000303033303330
        3330330300003003030303030303030300003033303330333033300300003003
        0303030303030303000030303330333033303303000030030303030303030303
        0000303330333033303330030000300303030303030303030000303033303330
        3330330300003003030303030303030300003000000000000000000300003333
        33333333333333330000}
      OnClick = SetBrushStyle
    end
    object BrushColor: TSpeedButton
      Left = 279
      Top = 8
      Width = 25
      Height = 25
      Glyph.Data = {
        66010000424D6601000000000000760000002800000014000000140000000100
        040000000000F000000000000000000000001000000010000000000000000000
        BF0000BF000000BFBF00BF000000BF00BF00BFBF0000C0C0C000808080000000
        FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF00999BBBBFAAAA
        4CCCFFFF0000999BBBBFAAAACCCCFFFF0000999BBBBFAAAA4CCCFFFF0000999B
        BBBFAAAACCCCFFFF0000999BBBBFAAAA4CCCFFFF0000999BBBBFAAAACCCCFFFF
        0000999BBBBFAAAA4CCCFFFF0000999BBBBFAAAACCCCFFFF0000999BBBBFAAAA
        4CCCFFFF0000999BBBBFAAAACCCCFFFF0000999BBBBFAAAA4CCCFFFF0000999B
        BBBFAAAACCCCFFFF0000999BBBBFAAAA4CCCFFFF0000999BBBBFAAAACCCCFFFF
        0000999BBBBFAAAA4CCCFFFF0000999BBBBFAAAACCCCFFFF0000999BBBBFAAAA
        4CCCFFFF0000999BBBBFAAAACCCCFFFF0000999BBBBFAAAA4CCCFFFF0000999B
        BBFFAAAFFCCCFFFF0000}
      OnClick = BrushColorClick
    end
  end
  object ScrollBox1: TScrollBox
    Left = 0
    Top = 123
    Width = 447
    Height = 254
    Align = alClient
    TabOrder = 4
    object Image: TImage
      Left = 0
      Top = 0
      Width = 443
      Height = 250
      Align = alClient
      AutoSize = True
      OnMouseDown = FormMouseDown
      OnMouseMove = FormMouseMove
      OnMouseUp = FormMouseUp
    end
  end
  object StatusBar1: TStatusBar
    Left = 0
    Top = 377
    Width = 447
    Height = 18
    Panels = <
      item
        Width = 150
      end
      item
        Width = 50
      end>
    SimplePanel = False
  end
  object MainMenu1: TMainMenu
    Left = 297
    Top = 148
    object File1: TMenuItem
      Caption = '&File'
      object New1: TMenuItem
        Caption = '&New'
        OnClick = New1Click
      end
      object Open1: TMenuItem
        Caption = '&Open...'
        OnClick = Open1Click
      end
      object Save1: TMenuItem
        Caption = '&Save'
        OnClick = Save1Click
      end
      object Saveas1: TMenuItem
        Caption = 'Save &as...'
        OnClick = SaveAs1Click
      end
      object Print1: TMenuItem
        Caption = '&Print'
        OnClick = Print1Click
      end
      object N1: TMenuItem
        Caption = '-'
      end
      object Exit1: TMenuItem
        Caption = 'E&xit'
        OnClick = Exit1Click
      end
    end
    object Edit1: TMenuItem
      Caption = '&Edit'
      object Cut1: TMenuItem
        Caption = 'Cu&t'
        ShortCut = 16472
        OnClick = Cut1Click
      end
      object Copy1: TMenuItem
        Caption = '&Copy'
        ShortCut = 16451
        OnClick = Copy1Click
      end
      object Paste1: TMenuItem
        Caption = '&Paste'
        ShortCut = 16470
        OnClick = Paste1Click
      end
    end
  end
  object OpenDialog1: TOpenDialog
    DefaultExt = 'bmp'
    Filter = 'Bitmap files (*.bmp)|*.bmp|All files|*.*'
    Left = 297
    Top = 188
  end
  object ColorDialog1: TColorDialog
    Ctl3D = True
    Left = 345
    Top = 148
  end
  object SaveDialog1: TSaveDialog
    DefaultExt = 'bmp'
    Filter = 'Bitmap files (*.bmp)|*.bmp|All files|*.*'
    Left = 345
    Top = 188
  end
end

//.h files codes--graphwin.h

#ifndef graphwinH
#define graphwinH
//---------------------------------------------------------------------------
#include
#include
#include
#include
#include
#include
#include
#include
#include
//---------------------------------------------------------------------------

enum TDrawingTool {dtLine, dtRectangle, dtEllipse, dtRoundRect};

class TFormMain : public TForm
{
__published:
    TPanel *Panel1;
    TPanel *PenBar;
    TPanel *BrushBar;
    TScrollBox *ScrollBox1;
    TImage *Image;
    TMainMenu *MainMenu1;
    TMenuItem *File1;
    TMenuItem *New1;
    TMenuItem *Open1;
    TMenuItem *Save1;
    TMenuItem *Saveas1;
    TMenuItem *Print1;
    TMenuItem *N1;
    TMenuItem *Exit1;
    TMenuItem *Edit1;
    TMenuItem *Cut1;
    TMenuItem *Copy1;
    TMenuItem *Paste1;
    TOpenDialog *OpenDialog1;
    TColorDialog *ColorDialog1;
    TSaveDialog *SaveDialog1;
    TStatusBar *StatusBar1;
    TSpeedButton *LineButton;
    TSpeedButton *RectangleButton;
    TSpeedButton *EllipseButton;
    TSpeedButton *RoundRectButton;
    TSpeedButton *PenButton;
    TSpeedButton *BrushButton;
    TSpeedButton *SolidPen;
    TSpeedButton *DashPen;
    TSpeedButton *DotPen;
    TSpeedButton *DashDotPen;
    TSpeedButton *DashDotDotPen;
    TSpeedButton *ClearPen;
    TSpeedButton *PenColor;
    TEdit *PenSize;
    TUpDown *PenWidth;
    TSpeedButton *SolidBrush;
    TSpeedButton *ClearBrush;
    TSpeedButton *HorizontalBrush;
    TSpeedButton *VerticalBrush;
    TSpeedButton *FDiagonalBrush;
    TSpeedButton *BDiagonalBrush;
    TSpeedButton *CrossBrush;
    TSpeedButton *DiagCrossBrush;
    TSpeedButton *BrushColor;
    void __fastcall RectangleButtonClick(TObject *Sender);
    void __fastcall EllipseButtonClick(TObject *Sender);
    void __fastcall RoundRectButtonClick(TObject *Sender);
    void __fastcall PenButtonClick(TObject *Sender);
    void __fastcall BrushButtonClick(TObject *Sender);
    void __fastcall SetPenStyle(TObject *Sender);
    void __fastcall PenColorClick(TObject *Sender);
    void __fastcall PenSizeChange(TObject *Sender);
    void __fastcall SetBrushStyle(TObject *Sender);
    void __fastcall BrushColorClick(TObject *Sender);
    void __fastcall FormMouseDown(TObject *Sender, TMouseButton Button,
      TShiftState Shift, int X, int Y);
    void __fastcall FormMouseMove(TObject *Sender, TShiftState Shift,
      int X, int Y);
    void __fastcall FormMouseUp(TObject *Sender, TMouseButton Button,
      TShiftState Shift, int X, int Y);
    void __fastcall New1Click(TObject *Sender);
    void __fastcall Open1Click(TObject *Sender);
    void __fastcall Save1Click(TObject *Sender);
    void __fastcall SaveAs1Click(TObject *Sender);
    void __fastcall Exit1Click(TObject *Sender);
    void __fastcall Cut1Click(TObject *Sender);
    void __fastcall Copy1Click(TObject *Sender);
    void __fastcall Paste1Click(TObject *Sender);
   
    void __fastcall LineButtonClick(TObject *Sender);
    void __fastcall Print1Click(TObject *Sender);
private:        // private user declarations
public:         // public user declarations
        bool Drawing;
        TPoint Origin, MovePt;
        TDrawingTool DrawingTool;
        AnsiString CurrentFile;

        void __fastcall DrawShape(TPoint TopLeft, TPoint BottomRight, TPenMode AMode);
        virtual __fastcall TFormMain(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern TFormMain *FormMain;
//---------------------------------------------------------------------------
#endif

//.cpp files codes--graphwin.cpp

#include
#pragma hdrstop
#include

#include "graphwin.h"
#include "bmpdlg.h"
#include
//---------------------------------------------------------------------------
#pragma resource "*.dfm"
TFormMain* FormMain;
//---------------------------------------------------------------------------
__fastcall TFormMain::TFormMain(TComponent* Owner)
  : TForm(Owner)
{
 Image->Canvas->MoveTo(0,0);
}
//---------------------------------------------------------------------------
void __fastcall TFormMain::LineButtonClick(TObject *Sender)
{
  DrawingTool = dtLine;
}
//---------------------------------------------------------------------
void __fastcall TFormMain::RectangleButtonClick(TObject *Sender)
{
  DrawingTool = dtRectangle;
}
//---------------------------------------------------------------------
void __fastcall TFormMain::EllipseButtonClick(TObject *Sender)
{
  DrawingTool = dtEllipse;
}
//---------------------------------------------------------------------
void __fastcall TFormMain::RoundRectButtonClick(TObject *Sender)
{
  DrawingTool = dtRoundRect;
}
//---------------------------------------------------------------------
void __fastcall TFormMain::PenButtonClick(TObject *Sender)
{
  PenBar->Visible = PenButton->Down;
}
//---------------------------------------------------------------------
void __fastcall TFormMain::BrushButtonClick(TObject *Sender)
{
  BrushBar->Visible = BrushButton->Down;
}
//---------------------------------------------------------------------
void __fastcall TFormMain::SetPenStyle(TObject *Sender)
{
    if (Sender == SolidPen){
       Image->Canvas->Pen->Style = psSolid;
    }
    else if (Sender == DashPen){
            Image->Canvas->Pen->Style = psDash;
    }
    else if (Sender == DotPen){
         Image->Canvas->Pen->Style = psDot;
    }
    else if (Sender == DashDotPen){
         Image->Canvas->Pen->Style = psDashDot;
    }
    else if (Sender == DashDotDotPen){
         Image->Canvas->Pen->Style = psDashDotDot;
    }
    else if (Sender == ClearPen){
         Image->Canvas->Pen->Style = psClear;
    }
}
//---------------------------------------------------------------------
void __fastcall TFormMain::PenColorClick(TObject *Sender)
{
  ColorDialog1->Color = Image->Canvas->Pen->Color;
  if (ColorDialog1->Execute()){
    Image->Canvas->Pen->Color = ColorDialog1->Color;
  }
}
//---------------------------------------------------------------------
void __fastcall TFormMain::PenSizeChange(TObject *Sender)
{
  Image->Canvas->Pen->Width = PenWidth->Position;
}
//---------------------------------------------------------------------
void __fastcall TFormMain::SetBrushStyle(TObject *Sender)
{
    if (Sender == SolidBrush){
       Image->Canvas->Brush->Style = bsSolid;
    }
    else if (Sender == ClearBrush){
         Image->Canvas->Brush->Style = bsClear;
    }
    else if (Sender == HorizontalBrush){
         Image->Canvas->Brush->Style = bsHorizontal;
    }
    else if (Sender == VerticalBrush){
         Image->Canvas->Brush->Style = bsVertical;
    }
    else if (Sender == FDiagonalBrush){
         Image->Canvas->Brush->Style = bsFDiagonal;
    }
    else if (Sender == BDiagonalBrush){
         Image->Canvas->Brush->Style = bsBDiagonal;
    }
    else if (Sender == CrossBrush){
         Image->Canvas->Brush->Style = bsCross;
    }
    else if (Sender == DiagCrossBrush){
         Image->Canvas->Brush->Style = bsDiagCross;
    }
}
//---------------------------------------------------------------------
void __fastcall TFormMain::BrushColorClick(TObject *Sender)
{
  ColorDialog1->Color = Image->Canvas->Brush->Color;
  if (ColorDialog1->Execute()){
    Image->Canvas->Brush->Color = ColorDialog1->Color;
  }
}
//---------------------------------------------------------------------
void __fastcall TFormMain::FormMouseDown(TObject *Sender, TMouseButton Button,
      TShiftState Shift, int X, int Y)
{
  Drawing = True;
  Image->Canvas->MoveTo(X, Y);
  Origin = Point(X, Y);
  MovePt = Origin;

  TVarRec tempvar[2] = {X, Y};
  StatusBar1->Panels->Items[0]->Text = Format("Origin: (%d, %d)", tempvar, 2);
}
//---------------------------------------------------------------------
void __fastcall TFormMain::FormMouseMove(TObject *Sender, TShiftState Shift,
      int X, int Y)
{
  if (Drawing){
    DrawShape(Origin, MovePt, pmNotXor);
    MovePt = Point(X, Y);
    DrawShape(Origin, MovePt, pmNotXor);
  }

  TVarRec tempvar[2] = {X, Y};
  StatusBar1->Panels->Items[1]->Text = Format("Current: (%d, %d)", tempvar, 2);
}
//---------------------------------------------------------------------
void __fastcall TFormMain::FormMouseUp(TObject *Sender, TMouseButton Button,
      TShiftState Shift, int X, int Y)
{
  if (Drawing){
    DrawShape(Origin, Point(X, Y), pmCopy);
    Drawing = False;
  }
}
//---------------------------------------------------------------------
void __fastcall TFormMain::New1Click(TObject *Sender)
{
     Graphics::TBitmap *Bitmap;

     NewBMPForm->ActiveControl = NewBMPForm->WidthEdit;
     NewBMPForm->WidthEdit->Text = IntToStr(Image->Picture->Graphic->Width);
     NewBMPForm->HeightEdit->Text = IntToStr(Image->Picture->Graphic->Height);
//     if (ShowModal() != idCancel){
     if (NewBMPForm->ShowModal() != IDCANCEL){
        Bitmap = new Graphics::TBitmap();
//        Bitmap->Create();
        Bitmap->Width = StrToInt(NewBMPForm->WidthEdit->Text);
        Bitmap->Height = StrToInt(NewBMPForm->HeightEdit->Text);
        Image->Picture->Graphic = Bitmap;
        CurrentFile = EmptyStr;
     }
}
//---------------------------------------------------------------------
void __fastcall TFormMain::Open1Click(TObject *Sender)
{
  if (OpenDialog1->Execute()){
    CurrentFile = OpenDialog1->FileName;
    Image->Picture->LoadFromFile(CurrentFile);
  }
}
//---------------------------------------------------------------------
void __fastcall TFormMain::Save1Click(TObject *Sender)
{
  if (CurrentFile != EmptyStr){
    Image->Picture->SaveToFile(CurrentFile);
  }
  else{
   SaveAs1Click(Sender);
  }
}
//---------------------------------------------------------------------
void __fastcall TFormMain::SaveAs1Click(TObject *Sender)
{
  if (SaveDialog1->Execute()){
    CurrentFile = SaveDialog1->FileName;
    Save1Click(Sender);
  }
}
//---------------------------------------------------------------------
void __fastcall TFormMain::Exit1Click(TObject *Sender)
{
  Close();
}
//---------------------------------------------------------------------
void __fastcall TFormMain::Cut1Click(TObject *Sender)
{
 TRect ARect;

 Copy1Click(Sender);

 Image->Canvas->CopyMode = cmWhiteness;
 ARect = Rect(0, 0, Image->Width, Image->Height);
 Image->Canvas->CopyRect(ARect, Image->Canvas, ARect);
 Image->Canvas->CopyMode = cmSrcCopy;
}

//---------------------------------------------------------------------
void __fastcall TFormMain::Copy1Click(TObject *Sender)
{
  Clipboard()->Assign(Image->Picture);
}

//---------------------------------------------------------------------
void __fastcall TFormMain::Paste1Click(TObject *Sender)
{

  Graphics::TBitmap *Bitmap;

  if (Clipboard()->HasFormat(CF_BITMAP)){
    Bitmap = new Graphics::TBitmap();
    try{
      Bitmap->Assign(Clipboard());
      Image->Canvas->Draw(0, 0, Bitmap);
      delete Bitmap;
    }
    catch(...){
      delete Bitmap;
    }
  }
}

//---------------------------------------------------------------------
void __fastcall TFormMain::DrawShape(TPoint TopLeft, TPoint BottomRight, TPenMode AMode){
    Image->Canvas->Pen->Mode = AMode;

    switch (DrawingTool){
           case dtLine : {
                Image->Canvas->MoveTo(TopLeft.x, TopLeft.y);
                Image->Canvas->LineTo(BottomRight.x, BottomRight.y);
                break;
           }

           case dtRectangle : {
                Image->Canvas->Rectangle(TopLeft.x, TopLeft.y, BottomRight.x, BottomRight.y);
                break;
           }

           case dtEllipse : {
                Image->Canvas->Ellipse(TopLeft.x, TopLeft.y, BottomRight.x, BottomRight.y);
                break;
           }

           case dtRoundRect : {
                Image->Canvas->RoundRect(TopLeft.x, TopLeft.y, BottomRight.x, BottomRight.y, (TopLeft.x - BottomRight.x)/2, (TopLeft.y - BottomRight.y)/2);
                break;
           }
    }
}
//---------------------------------------------------------------------
void __fastcall TFormMain::Print1Click(TObject *Sender)
{
    unsigned int BitmapInfoSize, BitmapImageSize;
    long DIBWidth, DIBHeight;
    PChar BitmapImage;
    Windows::PBitmapInfo BitmapInfo;
    Graphics::TBitmap *Bitmap;

    Printer()->BeginDoc();
    Bitmap = new Graphics::TBitmap();
    Bitmap->Assign(Image->Picture);
    GetDIBSizes(Bitmap->Handle, BitmapInfoSize, BitmapImageSize);
    BitmapInfo  = (PBitmapInfo) new char[BitmapInfoSize];
    BitmapImage = (PChar) new char [BitmapImageSize];
    GetDIB(Bitmap->Handle, 0, BitmapInfo, BitmapImage);
    DIBWidth  = BitmapInfo->bmiHeader.biWidth;
    DIBHeight = BitmapInfo->bmiHeader.biHeight;
    StretchDIBits(Printer()->Canvas->Handle,
                0, 0, DIBWidth, DIBHeight,
                0, 0, DIBWidth, DIBHeight,
                BitmapImage, BitmapInfo,
                DIB_RGB_COLORS, SRCCOPY);
    delete [] BitmapImage;
    delete [] BitmapInfo;
    delete Bitmap;

    Printer()->EndDoc();
}
//---------------------------------------------------------------------

 

How to track the mouse actions? well, we can add a field to a form object to track mouse actions.

To track whether a mouse button was pressed, you must add an object field to the form object. When you add a component to a form, C++Builder adds a field that represents that component to the form object, so that you can refer to the component by the name of its field. You can also add your own fields to forms by editing the type declaration in the form unit's header file.

In the following example, the form needs to track whether the user has pressed a mouse button. To do that, it adds a Boolean field and sets its value when the user presses the mouse button.

To add a field to an object, edit the object's type definition, specifying the field identifier and type after the public directive at the bottom of the declaration.
C++Builder "owns" any declarations before the public directive: that's where it puts the fields that represent controls and the methods that respond to events.

Example: Add a field to the form to track the mouse actions

The following code gives a form a field called Drawing of type bool, in the form object's declaration. It also adds two fields to store points Origin and
MovePt of type TPoint.

class TForm1 : public TForm
{
__published:  // IDE-managed Components
  void __fastcallFormMouseDown(TObject *Sender, TMouseButton Button,
  TShiftState Shift, int X, int Y);
  void __fastcall FormMouseMove(TObject *Sender, TShiftState Shift, int X,
  int Y);
  void __fastcall FormMouseUp(TObject *Sender, TMouseButton Button,
  TShiftState Shift, int X, int Y);
private: // User declarations
public:  // User declarations

  __fastcallTForm1(TComponent* Owner);
  bool Drawing;  //field to track whether button was pressed
   TPoint Origin, MovePt;  // fields to store points
};

When you have a Drawing field to track whether to draw, set it to true when the user presses the mouse button, and false when the user releases it:

void __fastcallTForm1::FormMouseDown(TObject *Sender, TMouseButton Button,
  TShiftState Shift, int X, int Y)
{
  Drawing = true;            // set the Drawing flag
  Canvas->MoveTo(X, Y);      // set pen position
}

void __fastcallTForm1::FormMouseUp(TObject *Sender, TMouseButton Button,
  TShiftState Shift, int X, int Y)
{
  Canvas->LineTo(X, Y);      // draw line from PenPos to (X, Y)
  Drawing = false;           // clear the Drawing flag
}

Then you can modify the OnMouseMove event handler to draw only when Drawing is true:

void __fastcallTForm1::FormMouseMove(TObject *Sender, TMouseButton Button,
  TShiftState Shift, int X, int Y)
{
  if (Drawing)
    Canvas->LineTo(X, Y); // only draw if mouse is down
}

This results in drawing only between the mouse-down and mouse-up events, but you still get a scribbled line that tracks the mouse movements instead of a straight line.

The problem is that each time you move the mouse, the mouse-move event handler calls LineTo, which moves the pen position, so by the time you release the button, you're lost the point where the straight line was supposed to start.

 

How to respond to the mouse event when using canvas to draw graphics in CBuilder?

Your application can respond to the mouse actions: mouse-button down, mouse moved, and mouse-button up. It can also respond to a click (a complete press-and-release, all in one place) that can be generated by some kinds of keystrokes (such as pressing Enter in a modal dialog box).
This section covers:

What's in a mouse event.

C++Builder has three mouse events: OnMouseDown event, OnMouseMove event, and OnMouseUp event.

When an application detects a mouse action, it calls whatever event handler you're defined for the corresponding event, passing five parameters. Use the information in those parameters to customize your responses to the events. The five parameters are as follows:

Parameter Meaning
Sender The object that detected the mouse action
Button Indicates which mouse button was involved: mbLeft, mbMiddle, or mbRight
Shift Indicates the state of the Alt, Ctrl, and Shift keys at the time of the mouse action
X, Y The coordinates where the event occurred

Most of the time, you need the coordinates returned in a mouse-event handler, but sometimes you also need to check Button to determine which mouse button caused the event.

Note: C++Builder uses the same criteria as Microsoft Windows in determining which mouse button has been pressed. Thus, if you have switched the default "primary" and "secondary" mouse buttons (so that the right mouse button is now the primary button), clicking the primary (right) button will record mbLeft as the value of the Button parameter.

Responding to a mouse-down action.

Whenever the user presses a button on the mouse, an OnMouseDown event goes to the object the pointer is over. The object can then respond to the event.
To respond to a mouse-down action, attach an event handler to the OnMouseDown event.

C++Builder generates an empty handler for a mouse-down event on the form:

void __fastcallTForm1::FormMouseDown(TObject *Sender, TMouseButton Button,
  TShiftState Shift, int X, int Y)
{
    bDrawState = true;
}

Responding to a mouse-up action.

An OnMouseUp event occurs whenever the user releases a mouse button. The event usually goes to the object the mouse cursor is over when the user presses the button, which is not necessarily the same object the cursor is over when the button is released. This enables you, for example, to draw a line as if it extended beyond the border of the form.

To respond to mouse-up actions, define a handler for the OnMouseUp event.

void __fastcall TForm1::FormMouseUp(TObject *Sender, TMouseButton Button,
      TShiftState Shift, int X, int Y)
{
    bDrawState = false;
}

Responding to a mouse move.

An OnMouseMove event occurs periodically when the user moves the mouse. The event goes to the object that was under the mouse pointer when the user pressed the button. This allows you to give the user some intermediate feedback by drawing temporary lines while the mouse moves.

To respond to mouse movements, define an event handler for the OnMouseMove event. This example uses mouse-move events to draw intermediate shapes on a form while the user holds down the mouse button, thus providing some feedback to the user. The OnMouseMove event handler draws a line on a form to the location of the OnMouseMove event:

void __fastcall TForm1::FormMouseMove(TObject *Sender, TMouseButton Button,
  TShiftState Shift, int X, int Y)
{
    if (bDrawState)
        Canvas->LineTo(X, Y); // draw line to current position
}

With this code, moving the mouse over the form causes drawing to follow the mouse, even before the mouse button is pressed. Mouse-move events occur even when you haven't pressed the mouse button. If you want to track whether there is a mouse button pressed, you need to add an object field to the form object.

 

Have you ever used photoshop? When you use the selection tool to select a region in the picture, a flowing line would appear around the selection area. Do you want to realize this function in your programs?

This is an example written by Delphi, you could convert it to other language as your need.

Put a timer component to the from, then assign the following codes.

var
  LineStep: Byte;

implementation

{$R *.DFM}

procedure DrawFlowLine(X, Y: Integer; Canvas: TCanvas); stdcall;
begin
  LineStep := LineStep shl 1;

  if LineStep = 0 then
    LineStep := 1;

  if (LineStep and 240) > 0 then
    Canvas.Pixels[X,Y] := clWhite
  else
    Canvas.Pixels[X,Y] := clBlack;
end;

procedure TForm1.Timer1Timer(Sender:TObject);
begin
  LineDDA(0, 0, 358, 371, @DrawFlowLine, LongInt(Canvas));
end;

Run the program, see what happen. This is a static flowing line, to make it move, you need to alternate the pixels everytime when timer1 is triggered.

 

How to draw on a graphic?

You don't need any components to manipulate your application't graphic objects. You can construct, draw on, save, and destroy graphic objects without ever drawing anything on screen. In fact, your applications rarely draw directly on a form. More often, an application operates on graphics and then uses an image control component to display the graphic on a form.

Once you move the application's drawing to the graphic in the image control, it is easy to add printing, clipboard, and loading and saving operations for any graphic objects. graphic objects can be bitmap files, drawings, icons or whatever other graphics classes that have been installed such as jpeg graphics.

Note: Because you are drawing on an offscreen image such as a TBitmap canvas, the image is not displayed until a control copies from a bitmap onto the control's canvas. That is, when drawing bitmaps and assigning them to an image control, the image appears only when the control has an opportunity to process its paint message. But if you are drawing directly onto the canvas property of a control, the picture object is displayed immediately.

How to make your graphics scrollable?

The graphic need not be the same size as the form: it can be either smaller or larger. By adding a scroll box control to the form and placing the graphic image inside it, you can display graphics that are much larger than the form or even larger than the screen. To add a scrollable graphic first you add a TScrollBox component and then you add the image control.

How to add an image control to your application?

An image control is a container component that allows you to display your bitmap objects. You use an image control to hold a bitmap that is not necessarily displayed all the time, or which an application needs to use to generate other pictures.

NoteAdding graphics to controls shows how to use graphics in controls.

How to place the control?

You can place an image control anywhere on a form. If you take advantage of the image control's ability to size itself to its picture, you need to set the top left corner only. If the image control is a nonvisible holder for a bitmap, you can place it anywhere, just as you would a nonvisual component.

If you drop the image control on a scroll box already aligned to the form's client area, this assures that the scroll box adds any scroll bars necessary to access offscreen portions of the image's picture. Then set the image control's properties.

 

What's the brush and how to use the brushes?

The Brush property of a canvas controls the way you fill areas, including the interior of shapes. Filling an area with a brush is a way of changing a large number of adjacent pixels in a specified way.

The brush has three properties you can manipulate:

  1. Color property changes the fill color.
  2. Style property changes the brush style.
  3. Bitmap property uses a bitmap as a brush pattern.

The values of these properties determine the way the canvas fills shapes or other areas. By default, every brush starts out white, with a solid style and no pattern bitmap.

You can use TBrushRecall for quick saving off and restoring the properties of brushes.

How to change the color of the brush?

A brush's color determines what color the canvas uses to fill shapes. To change the fill color, assign a value to the brush's Color property. Brush is used for background color in text and line drawing so you typically set the background color property.

You can set the brush color just as you do the pen color, in response to a click on a color grid on the brush's toolbar :

void __fastcallTForm1::BrushColorClick(TObject *Sender)
{
  Canvas->Brush->Color = BrushColor->BackgroundColor;
}

How to change the style of the brush?

A brush style determines what pattern the canvas uses to fill shapes. It lets you specify various ways to combine the brush's color with any colors already on the canvas. The predefined styles include solid color, no color, and various line and hatch patterns.

To change the style of a brush, set its Style property to one of the predefined values: bsSolid, bsClear, bsHorizontal, bsVertical, bsFDiagonal, bsBDiagonal, bsCross, or bsDiagCross.

This example sets brush styles by sharing a click-event handler for a set of eight brush-style buttons. All eight buttons are selected, the Object Inspector|Events|OnClick is set, and the OnClick handler is named SetBrushStyle. Here is the handler code:

void __fastcallTForm1::SetBrushStyle(TObject *Sender)
{
  if (Sender == SolidBrush)
    Canvas->Brush->Style = bsSolid;
  else if (Sender == ClearBrush)
    Canvas->Brush->Style = bsClear;
  else if (Sender == HorizontalBrush)
    Canvas->Brush->Style = bsHorizontal;
  else if (Sender == VerticalBrush)
    Canvas->Brush->Style = bsVertical;
  else if (Sender == FDiagonalBrush)
    Canvas->Brush->Style = bsFDiagonal;
  else if (Sender == BDiagonalBrush)
    Canvas->Brush->Style = bsBDiagonal;

  else if (Sender == CrossBrush)
    Canvas->Brush->Style = bsCross;
  else if (Sender == DiagCrossBrush)
    Canvas->Brush->Style = bsDiagCross;
}

The above event handler code could be further reduced by putting the brush style constants into the Tag properties of the brush style buttons. Then this event code would be something like:

void __fastcallTForm1::SetBrushStyle(TObject *Sender)
{
   if (Sender->InheritsFrom (__classid(TSpeedButton))
    Canvas->Brush->Style = (TBrushStyle) ((TSpeedButton *)Sender)->Tag;
}

How to set the bitmap property and use the FillRect method to draw a bitmap?

A brush's Bitmap property lets you specify a bitmap image for the brush to use as a pattern for filling shapes and other areas.

The following example loads a bitmap from a file and assigns it to the Brush of the Canvas of Form1:

BrushBmp->LoadFromFile("MyBitmap.bmp");

  Form1->Canvas->Brush->Bitmap = BrushBmp;
  Form1->Canvas->FillRect(Rect(0,0,100,100));

Note: The brush does not assume ownership of a bitmap object assigned to its Bitmap property. You must ensure that the Bitmap object remains valid for the lifetime of the Brush, and you must free the Bitmap object yourself afterwards.

How to read and set the pixels of a canvas?

You will notice that every canvas has an indexed Pixels property that represents the individual colored points that make up the image on the canvas. You rarely need to access Pixels directly, it is available only for convenience to perform small actions such as finding or setting a pixel's color.

Note: Setting and getting individual pixels is thousands of times slower than performing graphics operations on regions. Do not use the Pixel array property to access the image pixels of a general array. For high-performance access to image pixels, see the TBitmap::ScanLine property.

 

Pen and Brush in TCanvas

TCanvas is the base class that you can use to draw on it. In this article, you would learn how to use the pen to make some basic pictures on a canvas.

With the Canvas object, you can set the properties of a pen for drawing lines, a brush for filling shapes, a font for writing text, and an array of pixels to represent the image.

This section describes:

  1. Using pens.
  2. Using brushes.
  3. Reading and setting pixels.

How to use Pen?

The Pen property of a canvas controls the way lines appear, including lines drawn as the outlines of shapes. Drawing a straight line is really just changing a group of pixels that lie between two points.

The pen itself has four properties you can change: Color, Width, Style, and Mode.

  1. Color property changes the pen color.
  2. Width property changes the pen width.
  3. Style property changes the pen style.
  4. Mode property changes the pen mode.
  5. PenPos property getting the current drawing position.

The values of these properties determine how the pen changes the pixels in the line. By default, every pen starts out black, with a width of 1 pixel, a solid style, and a mode called copy that overwrites anything already on the canvas.

You can use TPenRecall for quick saving off and restoring the properties of pens.

How to change the colors of pen?

You can set the color of a pen as you would any other Color property at runtime. A pen's color determines the color of the lines the pen draws, including lines drawn as the boundaries of shapes, as well as other lines and polylines. To change the pen color, assign a value to the Color property of the pen.

To let the user choose a new color for the pen, put a color grid on the pen's toolbar. A color grid can set both foreground and background colors. For a non-grid pen style, you must consider the background color, which is drawn in the gaps between line segments. Background color comes from the Brush color property.

Since the user chooses a new color by clicking the grid, this code changes the pen's color in response to the OnClick event:

 

void __fastcallTForm1::PenColorClick(TObject *Sender)
{
  Canvas->Pen->Color = PenColor->ForegroundColor;
}

 

How to change the width of pen?

A pen's width determines the thickness, in pixels, of the lines it draws.

Note: When the thickness is greater than 1, Windows always draw solid lines, regardless of the value of the pen's Style property.

To change the pen width, assign a numeric value to the pen's Width property.

Suppose you have a scroll bar on the pen's toolbar to set width values for the pen. And suppose you want to update the label next to the scroll bar to provide feedback to the user. Using the scroll bar's position to determine the pen width, you update the pen width every time the position changes.

This is how to handle the scroll bar's OnChange event:

 

void __fastcallTForm1::PenWidthChange(TObject *Sender)
{
  Canvas->Pen->Width = PenWidth->Position;         // set the pen width directly
  PenSize->Caption = IntToStr(PenWidth->Position); // convert to string
}

 

How to change the style of pen?

A pen's Style property allows you to set solid lines, dashed lines, dotted lines, and so on.

VCL Note: For cross-platform applications deployed under Windows, Windows does not support dashed or dotted line styles for pens wider than one pixel and makes all larger pens solid, no matter what style you specify.

The task of setting the properties of pen is an ideal case for having different controls share same event handler to handle events. To determine which control actually got the event, you check the Sender parameter.

To create one click-event handler for six pen-style buttons on a pen's toolbar, do the following:

  1. Select all six pen-style buttons and select the Object Inspector|Events|OnClick event and in the Handler column, type SetPenStyle.
    C++Builder generates an empty click-event handler called SetPenStyle and attaches it to the OnClick events of all six buttons.
  2. Fill in the click-event handler by setting the pen's style depending on the value of Sender, which is the control that sent the click event:

 

void __fastcallTForm1::SetPenStyle(TObject *Sender)
{
  if (Sender == SolidPen)     Canvas->Pen->Style = psSolid;   else if (Sender == DashPen)     Canvas->Pen->Style = psDash;   else if (Sender == DotPen)     Canvas->Pen->Style = psDot;   else if (Sender == DashDotPen)     Canvas->Pen->Style = psDashDot;   else if (Sender == DashDotDotPen)     Canvas->Pen->Style = psDashDotDot; else if (Sender == ClearPen)     Canvas->Pen->Style = psClear; }

 

The above event handler code could be further reduced by putting the pen style constants into the Tag properties of the pen style buttons. Then this event code would be something like:

 

void __fastcallTForm1::SetPenStyle(TObject *Sender)
{
  if (Sender->InheritsFrom (__classid(TSpeedButton)) 
    Canvas->Pen->Style = (TPenStyle) ((TSpeedButton *)Sender)->Tag; }

 

How to get the pen mode?

A pen's Mode property lets you specify various ways to combine the pen's color with the color on the canvas. For example, the pen could always be black, be an inverse of the canvas background color, inverse of the pen color, and so on.

How to get the current position of the pen?

The current drawing position--the position from which the pen begins drawing its next line--is called the pen position. The canvas stores its pen position in its PenPos property. Pen position affects the drawing of lines only; for shapes and text, you specify all the coordinates you need.

To set the pen position, call the MoveTo method of the canvas. For example, the following code moves the pen position to the upper left corner of the canvas:

 

Canvas->MoveTo(0, 0);

 

Note: Drawing a line with the LineTo method also moves the current position to the endpoint of the line.

 

How to work with graphics and multimedia in CBuilder or Delphi?

Graphics and multimedia elements can add polish to your applications. C++Builder and Delphi offers a variety of ways to introduce these features into your application. To add graphical elements, you can insert pre-drawn pictures at design time, create them using graphical controls at design time, or draw them dynamically at runtime. To add multimedia capabilities, C++Builder includes special components that can play audio and video clips.

CLX: Multimedia components are available in the VCL only.

This following topics describe how to enhance your applications by introducing graphics or multimedia elements:

  1. Overview of graphics programming
  2. Working with multimedia

A glance to the graphics programming in CBuilder or Delphi

The VCL graphics components defined in the Graphics unit encapsulate the Windows Graphics Device Interface (GDI), making it easy to add graphics to your Windows applications. CLX graphics components defined in the QGraphics unit encapsulate the Qt graphics widgets for adding graphics to cross-platform applications.

To draw graphics in a C++Builder application, you draw on an object's canvas, rather than directly on the object. The canvas is a property of the object, and is itself an object. A main advantage of the canvas object is that it handles resources effectively and it takes care of device context, so your programs can use the same methods regardless of whether you are drawing on the screen, to a printer, or on bitmaps or metafiles (drawings in CLX). Canvases are available only at runtime, so you do all your work with canvases by writing code.

VCL: Since TCanvas is a wrapper resource manager around the Windows device context, you can also use all Windows GDI functions on the canvas. The Handle property of the canvas is the device context Handle.

CLXTCanvas is a wrapper resource manager around a Qt painter. The Handle property of the canvas is a typed pointer to an instance of a Qt painter object. Having this exposed allows you to use low-level Qt graphics library functions that require QPainterH.

How graphic images appear in your application depends on the type of object whose canvas you draw on. If you are drawing directly onto the canvas of a control, the picture is displayed immediately. However, if you draw on an offscreen image such as a TBitmap canvas, the image is not displayed until a control copies from the bitmap onto the control's canvas. That is, when drawing bitmaps and assigning them to an image control, the image appears only when the control has an opportunity to process its OnPaint message (VCL) or event (CLX).

When working with graphics, you often encounter the terms drawing and painting:

  • Drawing is the creation of a single, specific graphic element, such as a line or a shape, with code. In your code, you tell an object to draw a specific graphic in a specific place on its canvas by calling a drawing method of the canvas.
  • Painting is the creation of the entire appearance of an object. Painting usually involves drawing. That is, in response to OnPaint events, an object generally draws some graphics. An edit box, for example, paints itself by drawing a rectangle and then drawing some text inside. A shape control, on the other hand, paints itself by drawing a single graphic.

The following topics describe how to use graphics components to simplify your coding.

  1. Refreshing the screen
  2. Types of graphic objects
  3. Common properties and methods of canvases
  4. Handling multiple drawing objects in an application
  5. Drawing on a bitmap
  6. Loading and saving graphics files
  7. Using the clipboard with graphics
  8. Rubber banding example
 

This example show you how to convert a specified icon to a bitmap. Easy way follow me. Create a new project in c++builder enviroment, put an Image, a Button and an OpenDialog control on the Form1. Rename the button1 ConvertIcon2Bitmap, then add the following codes as its OnClick event handler.

void __fastcall TForm1::ConvertIcon2BitmapClick(TObject *Sender)

{
  OpenDialog1->DefaultExt = ".ICO";
  OpenDialog1->Filter = "icons (*.ico)|*.ICO";
  OpenDialog1->Options << ofOverwritePrompt << ofFileMustExist << ofHideReadOnly;
  if (OpenDialog1->Execute())
  {
    TIcon *pIcon = new TIcon();
    try
    {
      AnsiString szBitmap;
      pIcon->LoadFromFile(OpenDialog1->FileName);
      szBitmap = ChangeFileExt(OpenDialog1->FileName,".BMP");
      Image1->Width = pIcon->Width;
      Image1->Height = pIcon->Height;
      Image1->Canvas->Draw(0,0,pIcon);

      Image1->Picture->SaveToFile(szBitmap);
      ShowMessage(OpenDialog1->FileName + "has been saved to " + szBitmap);
    }
    __finally
    {
      delete pIcon;
    }
}

Run your project to see the result and good luck!