Тема: Есть ли на VB команда выбора цвета?
Есть ли на VB команда идентичная (acad_colordlg colornum [flag])? Надо в форме VB позволить пользователю выбирать цвет.
Информационный портал для профессионалов в области САПР
Вы не вошли. Пожалуйста, войдите или зарегистрируйтесь.
Форумы CADUser → Программирование → VBA → Есть ли на VB команда выбора цвета?
Страницы 1
Чтобы отправить ответ, вы должны войти или зарегистрироваться
Есть ли на VB команда идентичная (acad_colordlg colornum [flag])? Надо в форме VB позволить пользователю выбирать цвет.
по меему только через thisdrawing.setvariable "color",#цвета(от 1до 256). Другого способа не нашел.
В продолжение вопроса...
А есть ли способ присвоить именнваный цвет, например red?
правильно будет не 'color' a 'cecolor'
> Pavelii
Функция
Private Declare Function acedSetColorDialog Lib "acad.exe" (color As Long, ByVal bAllowMetaColor As Boolean, ByVal nCurLayerColor As Long) As Boolean
Пример использования
http://cadhlp.kulichki.com/vba/Samples/acentity.htm
> ssn
Object.Color=1 Object.Color=acRed
Уважаемый Bender откуда у вас такая информация о существовании функции:
acedSetColorDialog
?
Может вы ещё какие-нибудь функции знаете и где найти их список и почитать про них побольше?
> Миша
А вот с того самого сайта.
А где узнать побольше - единственное что могу предложить
https://www.caduser.ru/forum/topic6621.html
Declare Function acedSetColorDialog Lib "acad.exe"
Браво!
Такие примеры надо приводить в ветках "..vs..", только с другими, недоступными из LISP функциями.
Могу предложить еще несколько функций из библитеки acad.exe - ...ProgressBar... Назначение понятно из названия. Исходный текст с примером http://www.vbdesign.net/expresso/showth … &icp=1. Но может не открываться. Я его не много модифицировал.
Option Explicit Private Declare Function ProgressMeter Lib "acad.exe" Alias "?acedSetStatusBarProgressMeter@@YAHPBDHH@Z" (ByVal strCaption As String, ByVal intmin As Integer, ByVal intmax As Integer) As Boolean Private Declare Function SetProgBarPos Lib "acad.exe" Alias "?acedSetStatusBarProgressMeterPos@@YAHH@Z" (ByVal intVal As Integer) As Boolean Private Declare Function RestoreStatus Lib "acad.exe" Alias "?acedRestoreStatusBar@@YAXXZ" () As Boolean Private Sub progressBarOn(ByVal captionProgressBar As String, ByVal minProgressBar As Integer, ByVal maxProgressBar As Integer) On Error Resume Next ProgressMeter captionProgressBar, minProgressBar, maxProgressBar End Sub Private Sub progressBarOff() On Error Resume Next RestoreStatus End Sub Private Sub progressBarRun(ByVal i As Integer) On Error Resume Next SetProgBarPos (i) End Sub Public Sub TestProgressBar() Dim objEnt As AcadEntity Dim i As Integer progressBarOn "Примитивы пространста модели", 0, ThisDrawing.ModelSpace.Count For Each objEnt In ThisDrawing.ModelSpace i = i + 1 progressBarRun i Next progressBarOff End Sub
Решил воспользоваться данной функцией, но никак не пойму где ошибка
в приведённом ниже коде. Если кто знает помогите пожалуйсто.
Диалоговое окно грузится как положено, но при выходе из него,
хоть по Ok, хоть по Cancel даёт ошибку:
"Bad DLL calling convention (Error 49)"
Private Declare Function acedSetColorDialog Lib "acad.exe" _ (color As Long, ByVal bAllowMetaColor As Boolean, ByVal nCurLayerColor As Long) As Boolean Sub ColorDlg() Dim AllowMetaColor As Boolean, Res As Boolean Dim DefColor As Long, NewColor As Long NewColor = 7 bAllowMetaColor = True DefColor = 7 Res = acedSetColorDialog(NewColor, AllowMetaColor, DefColor) End Sub
И ещё, ни кто случайно не знает, как работать с аналогичной функцией:
acedSetColorDialogTrueColor
А то Lisp код (acad_truecolordlg (420 . 1005220)) через командую строку
не отрабатывает пока макрос не завершит работу, поэтому приходится макрос
бить на две части и прехватывать изменение системной переменной "USERS1".
Можно воспользоваться API.
http://www.mvps.org/access/api/api0060.htm
> Gogi
Private Declare Function CHOOSECOLOR Lib "comdlg32.dll" Alias "ChooseColorA" (pChoosecolor As CHOOSECOLOR) As Long
При помощи этого мы задействуем системную палитру цветов, значение которое она нам вернет не будет значением ACI, это означает что мы не сможем воспользоваться связкой
AnyObj.Color = cc.rgbResult
> Gogi
Спасибо за ссылку, интересно покапаться.
Однако SmeL прав, работая в AutoCAD необходима возможность работать
в его цветовых системах, с их возможностями.
" AnyObj.Color = cc.rgbResult "
Хочу уточнить, с данной связкой как раз проблем нет. Начиная с AutoCAD 2004
для задания цвета используется объект:
AnyObj.TrueColor
и в нём есть метод SetRGB. Метод Color оставлен временно, только для
совместимости со старыми приложениями.
> bender
Выше приведённая декларация функции acedSetColorDialog возможно работала
в AutoCAD версий с 2000 по 2002.
Начиная с AutoCAD версии 2004, всё изменилось. Данная функция больше не используется.
Однако, ею всё ещё можно воспользоваться, ниже приведён код работы с ней.
Private Declare Function acedSetColorDialog Lib "acad.exe" _ (Color As acColor, ByVal AllowMetaColor As Byte) As Byte ' Color - передаёт значение по умолчанию и принимает новое; ' AllowMetaColor - определяет активность кнопок ByLayer и ByBlock: ' 0 - не активны; ' 1 - активны. Sub DlgColorACI() Dim Color As acColor, ColorOld As acColor Dim AllowMetaColor As Byte, Result As Byte Color = acByLayer AllowMetaColor = 1 On Error Resume Next ColorOld = Color Result = acedSetColorDialog(Color, AllowMetaColor) On Error GoTo 0 If Color = ColorOld Then MsgBox "Выбор был отменён!", vbExclamation Else MsgBox "Вы выбрали: " & Color & " цвет!", vbInformation End If End Sub
При выходе из функции по идее должна передать:
0 - при отмене выбора;
1 - если цвет был выбран.
На самом деле на выходе передаёт ошибку.
Возможная причина будет описана в конце, при описании новой функции.
Но, как я выше сказал, данная функция больше не используется, поэтому и нет
смысла с нею связываться.
За диалоговое окно выбора цвета отвечает Dll-библиотека Color.dll, само
диалоговое окно расположено в ресурсной библиотеке ColorRes.dll.
Например Lisp функция acad_colordlg вызывает через Arx-модуль AcApp.arx
функцию DoColorDialog напрямую из Color.dll. Поэтому думаю следует идти тем же путём.
Ниже приведён код работы с данной функцией.
Private Declare Function DoColorDialog Lib "color.dll" _ (ByVal NotUsed As Long, ByVal ColorCurrent As acColor, ByVal NotUsed As Long, _ ByVal NotUsed As Long, ByVal AllowMetaColor As Byte) As acColor ' ColorCurrent - передаёт значение по умолчанию; ' AllowMetaColor - определяет активность кнопок ByLayer и ByBlock: ' 0 - не активны; ' 1 - активны. ' Возвращает: ' -1 - при отмене выбора; ' 0-256 - выбранный цвет. Sub DlgColorACI() Dim Color As acColor, ColorCurrent As acColor Dim AllowMetaColor As Byte ColorCurrent = 125 AllowMetaColor = 1 Color = DoColorDialog(0, ColorCurrent, 0, 0, AllowMetaColor) If Color = -1 Then MsgBox "Выбор был отменён!", vbExclamation Else MsgBox "Вы выбрали: " & Color & " цвет!", vbInformation End If End Sub
Для работы со всеми цветавыми системами AutoCAD, используется функция:
acedSetColorDialogTrueColor из acad.exe или DoColorDialogTrueColor из color.dll
Однако с функцией DoColorDialogTrueColor на прямую, связываться не советую.
Тип Boolean не желательно использовать при работе с данными функциями, т. к. в
VBA в отличии от остальных языков, он имеет 2 байта: True=1 и False=-1.
Ниже приведён код работы с функцией acedSetColorDialogTrueColor.
Type tColor NotKnow As Long Color As Long ColorName As Long ColorBook As Long End Type Private Declare Function acedSetColorDialogTrueColor Lib "acad.exe" _ (Color As tColor, ByVal AllowMetaColor As Byte, _ ColorCurrent As tColor, ByVal ColorSystems As Byte) As Byte ' Color - передаёт значение по умолчанию и принимает новое; ' AllowMetaColor - определяет активность кнопок ByLayer и ByBlock: ' 0 - не активны; ' 1 - активны; ' ColorCurrent - не используется, но обязано быть определено, возможно было ' задекларировано на будущее, для передачи цвета по умолчанию; ' ColorSystems - определяет набор отображаемых вкладок с цветавыми системами: ' 1 - ACI; ' 2 - RGB; ' 4 - BookName; ' Сумма данных значений даёт требуемый набор: ' 1+2=3 - ACI+RGB; ' 1+4=5 - ACI+BookName; ' 2+4=6 - RGB+BookName; ' 1+2+4=7 - ACI+RGB+BookName. ' Sub DlgTrueColor() Dim Color As AcadAcCmColor Dim AllowMetaColor As Byte, ColorSystems As Byte, Result As Byte Dim ColorOld As Long Dim ColorLong As tColor, ColorCurrent As tColor ' При переносе данной строки из конца в другое место и выборе именованого цвета AutoCAD вылетает. With ColorLong .NotKnow = 1691390208 ' В необходимости данного параметра разобраться не смог, видимо какой-то адресс, поэтому просто передаём данное значение. .Color = -1024366560 ' Значение цвета по умолчанию в формате AcCmEntityColor или AcadEntityObj.TrueColor.EntityColor .ColorName = 0 ' Адрес по каторому располагается имя цвета. .ColorBook = 0 ' Адрес по которому располагается имя библиотеки цвета. End With With ColorCurrent .NotKnow = 1691390208 .Color = -1023410169 .ColorName = 0 .ColorBook = 0 End With AllowMetaColor = 1 ColorSystems = 7 On Error Resume Next ColorOld = ColorLong.Color Result = acedSetColorDialogTrueColor(ColorLong, AllowMetaColor, ColorCurrent, ColorSystems) On Error GoTo 0 If ColorLong.Color = ColorOld Then MsgBox "Выбор был отменён!", vbExclamation Else Set Color = Application.GetInterfaceObject("AutoCAD.AcCmColor.16") Color.EntityColor = ColorLong.Color If Color.ColorMethod = acColorMethodByRGB Then MsgBox "Вы выбрали: " & Chr(13) & Chr(10) & _ " цветовая система: RGB - " & Color.ColorMethod & Chr(13) & Chr(10) & _ " цвет: R" & Color.Red & ":G" & Color.Green & ":B" & Color.Blue, vbInformation Else MsgBox "Вы выбрали: " & Chr(13) & Chr(10) & _ " цветовая система: ACI - " & Color.ColorMethod & Chr(13) & Chr(10) & _ " цвет: " & Color.ColorIndex, vbInformation End If End If End Sub
При выходе из функции по идее должна передать:
0 - при отмене выбора;
1 - если цвет был выбран.
На самом деле на выходе передаёт ошибку.
Данная проблема по всей видимости в следующем: данная функция не предназначена для
внешнего использования. Поэтому в ней нет, на выходе, обнуления флага ошибки.
Определение же цветовой системы и выбранного цвета осуществляется как раз по
соответствующей ошибке. То есть, обрабатывается имя цвета и если возникла ошибка
идёт переход на обработку цвета TrueColor, если возникла ошибка идёт переход на
обработку цвета ACI. Сами же разработчики на них не обращают внимания, например
при выборе цвета в диалоговом окне команды TABLE из модуля AcTabll.arx идут сплошные ошибки.
Но есть и более серьёзная проблема при использовании данной функции.
Если я не ошибаюсь, AutoCAD пишется на Assembler и поэтому многие параметры во внутренних
функциях передаются через адреса.
В данной функции через адрес передаются имена цвета и библиотеки цвета. Поэтому на
VBA нет возможности ни передать значение именованного цвета, ни получить имя выбранного
цвета в именованной системе. Назад мы получаем только адреса, где расположены данные имена.
Возможно знатоки API функций знают какие нибудь функции в Windows, с помощью которых
можно по полученным адресам считать возвращённые имена. Если знаете надеюсь поделитесь.
У разработчиков Arx приложений таких проблем нет, они могут просто вставить код
на Assembler и без проблем считать любую информацию откуда угодно. В VBA для приложений
ни каких подобных возможностей просто нет. Поэтому передать и получить мы можем только
RGB значение именованного цвета.
Ниже приводятся несколько процедур по работе со значениями цвета.
Цвет хранится в шестнадцатеричном формате:
C2010203
С2 - номер цветовой системы AutoCAD
01 - Красный цвет в RGB и 00 в ACI, ByLayer, ByBlock
02 - Зелёный цвет в RGB и 00 в ACI, ByLayer, ByBlock
03 - Синий цвет в RGB и значение цвета в ACI, 00 в ByLayer и ByBlock
Цвет, в стандартной системе Windows, имеет другой порядок
00030201
01 - Красный
02 - Зелёный
03 - Синий
Данная процедура получает значение цвета напрямую из шестнадцатеричного кода цвета.
Особого смысла в ниже приведённой процедуре нет, дана просто для наглядности.
Sub HexToColor() Dim ColorMethod As Byte, ColorIndex As Byte Dim Red As Byte, Green As Byte, Blue As Byte Dim ColorHex As String ColorHex = "C2F16820" ColorMethod = Val("&H" & Left(ColorHex, 2)) Select Case ColorMethod Case 192: ColorIndex = 256 ' ByLayer Case 193: ColorIndex = 0 ' ByBlock Case 194 ' ByRGB Red = Val("&H" & Mid(ColorHex, 3, 2)) Green = Val("&H" & Mid(ColorHex, 5, 2)) Blue = Val("&H" & Right(ColorHex, 2)) Case 195 ' ByACI ColorIndex = Val("&H" & Right(ColorHex, 2)) Case 197 ' Foreground End Select End Sub
Ниже приведённая процедура делает в принципе тоже, что и предыдущая.
Получает значение цвета из формата AcCmEntityColor.
Sub EntityColorToColor() Dim ColorMethod As Byte, ColorIndex As acColor Dim Red As Byte, Green As Byte, Blue As Byte Dim ColorLong As Long ColorLong = -1024366560 ColorMethod = (ColorLong And &H7F000000) \ &H1000000 If ColorLong < 0 Then ColorMethod = ColorMethod Or &H80 Select Case ColorMethod Case acColorMethodByLayer: ColorIndex = 256 Case acColorMethodByBlock: ColorIndex = 0 Case acColorMethodByRGB Red = (ColorLong And &HFF0000) \ &H10000 Green = (ColorLong And &HFF00&) \ &H100& Blue = ColorLong And &HFF& Case acColorMethodByACI ColorIndex = ColorLong And &HFF& Case acColorMethodForeground End Select End Sub
Ниже приведённая процедура переводит значение цвета в формат AcCmEntityColor.
Sub ColorToHex() Dim ColorMethod As AcColorMethod Dim ColorIndex As acColor Dim Red As Byte, Green As Byte, Blue As Byte Dim EntityColor As Long Dim ColorHex As String ColorMethod = acColorMethodByRGB If ColorMethod = acColorMethodByRGB Then Red = 241 Green = 104 Blue = 32 ColorHex = Hex(ColorMethod) & Hex(Red) & Hex(Green) & Hex(Blue) ElseIf ColorMethod = acColorMethodByACI Then ColorIndex = acYellow ColorHex = Hex(ColorMethod) & "0000" & Hex(ColorIndex) Else ColorHex = Hex(ColorMethod) & "000000" End If EntityColor = Val("&H" & ColorHex) End Sub
До полной коллекции:
Процедура перевода значения цвета стандартного Windows в формат AcCmEntityColor
Sub winRGBToacRGB() Dim winRGB as Long, acRGB as Long winRGB = RGB(241, 104, 32) acRGB = Val("&HC2" & Hex(winRGB And &HFF&) & Hex((winRGB And &HFF00&) \ &H100&) & _ Hex((winRGB And &HFF0000) \ &H10000)) ' или acRGB = Val("&H" & Hex(acColorMethodByRGB) & Hex(winRGB And &HFF&) & _ Hex((winRGB And &HFF00&) \ &H100&) & Hex((winRGB And &HFF0000) \ &H10000)) End Sub
Процедура перевода значения цвета из формата AcCmEntityColor в стандартный Windows
Sub acRGBTowinRGB() Dim winRGB as Long, acRGB as Long acRGB = -1024366560 winRGB = Val("&H" & Hex(acRGB And &HFF&) & Hex((acRGB And &HFF00&) \ &H100&) & _ Hex((acRGB And &HFF0000) \ &H10000)) End Sub
Прошу прощения, в выше приведённых примерах, при использовании функции Hex(), не учёл, что данная функция откидывает старший (левый) полубайт, если он равен нулю.
Поэтому правильная запись, во всех приведённых примерах использующих функцыю Hex(), будет выглядеть так:
Format(Hex(), "#00")
И кроме того, в одном из выше приведённых примеров, я задекларировал и определил объект Color следующим методом:
Dim Color As AcadAcCmColor Set Color = Application.GetInterfaceObject("AutoCAD.AcCmColor.16")
Желательно так не делать, иначе вы привязываете свой код к конкретной версии AutoCAD.
Лучше использовать следующий метод:
Dim Color As New AcadAcCmColor
Страницы 1
Чтобы отправить ответ, вы должны войти или зарегистрироваться
Форумы CADUser → Программирование → VBA → Есть ли на VB команда выбора цвета?
Форум работает на PunBB, при поддержке Informer Technologies, Inc