Хочу RoundRect, уважающую пользовательскую систему координат

Программирование на Visual Basic, главный форум. Обсуждение тем программирования на VB 1—6.
Даже если вы плохо разбираетесь в VB и программировании вообще — тут вам помогут. В разумных пределах, конечно.
Правила форума
Темы, в которых будет сначала написано «что нужно сделать», а затем просьба «помогите», будут закрыты.
Читайте требования к создаваемым темам.
tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Хочу RoundRect, уважающую пользовательскую систему координат

Сообщение tyomitch » 27.05.2006 (Сб) 5:23

Иногда бывает удобно задать для PictureBoc/UserControl хитрую нестандартную систему координат, и работать в ней. В таком случае API RoundRect неприменима непосредственно.

Решил написать замену на чистом VB:
Код: Выделить всё
Sub RoundRect(ByVal ctx As Object, ByVal Left As Single, ByVal Top As Single, ByVal Right As Single, ByVal Bottom As Single, ByVal RadiusX As Single, ByVal RadiusY As Single)
Const pi = 3.14159265358979
'учесть баг в VB: аспект не масштабируется
Dim Aspect As Single, Radius As Single
    Radius = RadiusY * ctx.ScaleY(1, vbUser, vbPixels) / ctx.ScaleX(1, vbUser, vbPixels)
    Aspect = Abs(Radius) / RadiusX

If ctx.FillStyle = vbFSSolid Then
    Radius = Abs(Radius)
    ctx.Circle (Left + RadiusX, Top + RadiusY), Radius, , , , Aspect
    ctx.Circle (Right - RadiusX, Top + RadiusY), Radius, , , , Aspect
    ctx.Circle (Left + RadiusX, Bottom - RadiusY), Radius, , , , Aspect
    ctx.Circle (Right - RadiusX, Bottom - RadiusY), Radius, , , , Aspect
    ctx.Line (Left + RadiusX, Top)-(Right - RadiusX, Bottom), , B
    ctx.Line (Left, Top + RadiusY)-(Right, Bottom - RadiusY), , B
Else
    If Radius < 0 Then
        Radius = -Radius
        ctx.Circle (Left + RadiusX, Bottom - RadiusY), Radius, , pi * 0.5, pi, Aspect
        ctx.Circle (Right - RadiusX, Bottom - RadiusY), Radius, , 0, pi * 0.5, Aspect
        ctx.Circle (Left + RadiusX, Top + RadiusY), Radius, , pi, pi * 1.5, Aspect
        ctx.Circle (Right - RadiusX, Top + RadiusY), Radius, , pi * 1.5, 0, Aspect
    Else
        ctx.Circle (Left + RadiusX, Top + RadiusY), Radius, , pi * 0.5, pi, Aspect
        ctx.Circle (Right - RadiusX, Top + RadiusY), Radius, , 0, pi * 0.5, Aspect
        ctx.Circle (Left + RadiusX, Bottom - RadiusY), Radius, , pi, pi * 1.5, Aspect
        ctx.Circle (Right - RadiusX, Bottom - RadiusY), Radius, , pi * 1.5, 0, Aspect
    End If
    ctx.Line (Left + RadiusX, Top)-(Right - RadiusX, Top)
    ctx.Line (Left + RadiusX, Bottom)-(Right - RadiusX, Bottom)
    ctx.Line (Left, Top + RadiusY)-(Left, Bottom - RadiusY), , B
    ctx.Line (Right, Top + RadiusY)-(Right, Bottom - RadiusY), , B
End If
End Sub


Иногда (в частности, при "квадратных" и "вытянутых по горизонтали" пикселах) этот код работает. Что дописать, чтобы работал всегда?
Изображение

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 27.05.2006 (Сб) 6:44

Код: Выделить всё
Option Explicit

Private Declare Function SetMapMode Lib "gdi32.dll" (ByVal hdc As Long, ByVal nMapMode As Long) As Long
Private Declare Function SetWindowExtEx Lib "gdi32.dll" (ByVal hdc As Long, ByVal nX As Long, ByVal nY As Long, ByRef lpSize As Any) As Long
Private Declare Function SetViewportExtEx Lib "gdi32.dll" (ByVal hdc As Long, ByVal nX As Long, ByVal nY As Long, ByRef lpSize As Any) As Long
Private Declare Function RoundRect Lib "gdi32.dll" (ByVal hdc As Long, ByVal X1 As Long, ByVal Y1 As Long, ByVal X2 As Long, ByVal Y2 As Long, ByVal X3 As Long, ByVal Y3 As Long) As Long

Private Const MM_ANISOTROPIC As Long = 8


Private Sub Form_Load()
  Me.AutoRedraw = False
  Me.Width = Me.ScaleX(640, vbPixels, vbTwips)
  Me.Height = Me.ScaleY(480, vbPixels, vbTwips)
End Sub

Private Sub Command1_Click()
  Const X_UNITS_COUNT As Long = 5
  Const Y_UNITS_COUNT As Long = 5
 
  SetMapMode Me.hdc, MM_ANISOTROPIC
  SetWindowExtEx Me.hdc, X_UNITS_COUNT, Y_UNITS_COUNT, ByVal 0&
  SetViewportExtEx Me.hdc, Me.ScaleX(Me.Width, vbTwips, vbPixels), Me.ScaleY(Me.Height, vbTwips, vbPixels), ByVal 0&
 
  RoundRect Me.hdc, 1, 1, 4, 4, 1, 1
End Sub


;)
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас


Вернуться в Visual Basic 1–6

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 146

    TopList  
cron