[Closed] Better way to create a Color Pallete
Recently i started to a simple color pallete tool using KnownColor.
I was inspire by this script http://lonerobot.net/?p=246
The script below shows my firts try where i used a simple label ctrl to
represent a color sample. Main poblem is that script opens slowly.
Is there a better way to perform this?
thanks in advance.
(
global paletteForm
try(paletteForm.close())catch()
fn defColor r g b = ((dotNetClass "System.Drawing.Color").FromArgb r g b)
fn defSize x y = (dotNetObject "System.Drawing.Size" x y)
fn defPoint x y = (dotNetObject "System.Drawing.Point" x y)
fn defFont fName fSize = (dotNetObject "System.Drawing.Font" fName fSize ((dotNetClass "System.Drawing.FontStyle").bold))
fn paletteSamplesCoords count: w: h: columns: rows: locX: locY: spaceBtw: =
(
local cnt = 1, start = 0, resultArr = #()
local cntArr = for n in 1 to rows-1 collect n*columns
for i in 1 to count do
(
local fItm = finditem cntArr i, offX = spaceBtw*(cnt-1)
append resultArr (point2 ((locX + ((cnt-1) * w)) + offX) (locY + start)) ; cnt+=1
if fItm != 0 do (cnt = 1 ; start = (h * fItm) + (spaceBtw * fItm))
) ; resultArr
)
local C1 = (defColor 25 25 25), C2 = (defColor 220 220 220), C3 = (defColor 60 100 160)
local F1 = (defFont "Swis721 Cn BT" 9)
local CRS = (dotNetClass "Cursors").Hand
local paletteTextEdit, paletteBtnArr = #()
local enumClass = dotNetClass "Enum"
local colorClass = dotNetClass "System.Drawing.Color"
local kcArr = enumClass.GetNames (dotNet.getType "System.Drawing.KnownColor")
local clrNameArr = for i in kcArr.count-7 to 28 by -1 collect (colorClass.FromName kcArr[i])
local clrCoordsArr = paletteSamplesCoords count:clrNameArr.count w:17 h:17 columns:10 rows:14 locX:8 locY:10 spaceBtw:0
fn defForm dnForm w h x y =
(
dnForm.ShowInTaskbar = false
dnForm.Text = " ColorPalette1"
dnForm.ClientSize = defSize w h
dnForm.StartPosition = dnForm.StartPosition.Manual ; dnForm.DesktopLocation = defPoint x y
dnForm.FormBorderStyle = dnForm.FormBorderStyle.FixedToolWindow ; dnForm.BackColor = C1
)
fn defTextEdit dxTextE w h locX locY txt active:true upper:false maxlenght:false =
(
dxTextE.Size = defSize w h
dxTextE.Location = defPoint locX locY
dxTextE.Properties.AutoHeight = false
dxTextE.BackColor = C1 ; dxTextE.ForeColor = C2
dxTextE.Text = txt ; dxTextE.Font = F1 ; dxTextE.Enabled = active
dxTextE.BorderStyle = dxTextE.BorderStyle.Simple
dxTextE.Properties.Appearance.BorderColor = C3
dxTextE.Properties.Appearance.TextOptions.HAlignment = dxTextE.Properties.Appearance.TextOptions.HAlignment.Center
if upper == true do (dxTextE.Properties.CharacterCasing = dxTextE.Properties.CharacterCasing.Upper)
if maxlenght == true do (dxTextE.Properties.MaxLength = 6)
)
fn defClrPltBtn dxClrPltBtn w h locX locY clr =
(
dxClrPltBtn.Size = defSize w h
dxClrPltBtn.Location = defPoint locX locY
dxClrPltBtn.AutoSizeMode = dxClrPltBtn.AutoSizeMode.None
dxClrPltBtn.Appearance.BackColor = clr
dxClrPltBtn.BorderStyle = dxClrPltBtn.BorderStyle.Simple
dxClrPltBtn.Appearance.BorderColor = C1 ; dxClrPltBtn.Cursor = CRS
dotNet.addEventHandler dxClrPltBtn "MouseHover" (fn mh s e = (s.Appearance.BorderColor = s.Appearance.BackColor))
dotNet.addEventHandler dxClrPltBtn "MouseLeave" (fn ml s e = (s.Appearance.BorderColor = C1))
)
paletteForm = dotNetObject "Form" ; defForm paletteForm 186 280 50 110 ; paletteForm.SuspendLayout()
paletteTextEdit = dotNetObject "DevExpress.XtraEditors.TextEdit" ; defTextEdit paletteTextEdit 170 20 8 253 " " active:false
paletteBtnArr = for b in 1 to clrCoordsArr.count collect
(
local paletteBtn = dotNetObject "DevExpress.XtraEditors.LabelControl"
(defClrPltBtn paletteBtn 17 17 clrCoordsArr[b].x clrCoordsArr[b].y clrNameArr[b])
dotNet.addEventHandler paletteBtn "MouseDown" (fn paletteBtnMD s e = paletteTextEdit.Text = (((s.Appearance.BackColor).ToKnownColor()).ToString()))
paletteBtn
)
join paletteBtnArr #(paletteTITLE, paletteTextEdit)
paletteForm.Controls.addRange(paletteBtnArr)
local sysPointer = dotNetObject "System.IntPtr" (windows.getMaxHWND())
local maxHandle = dotNetObject "maxCustomControls.win32HandleWrapper" sysPointer
paletteForm.Show maxHandle ; paletteForm.ResumeLayout()
)
My second try (fester solution but accurate) where i used a BG Image to
represent a color pallete
(
global paletteForm
try(paletteForm.close())catch()
fn defColor r g b = ((dotNetClass "System.Drawing.Color").FromArgb r g b)
fn defSolidBrush clr = (dotNetObject "System.Drawing.SolidBrush" clr)
fn defRect x y w h = (dotNetObject "System.Drawing.Rectangle" x y w h)
fn defSize x y = (dotNetObject "System.Drawing.Size" x y)
fn defPoint x y = (dotNetObject "System.Drawing.Point" x y)
fn defFont fName fSize = (dotNetObject "System.Drawing.Font" fName fSize ((dotNetClass "System.Drawing.FontStyle").bold))
fn defBitmap w h = (dotNetObject "System.Drawing.Bitmap" w h)
fn defGraphics bmpImg = ((dotNetClass "System.Drawing.Graphics").FromImage bmpImg)
fn defPen clr pt = (dotNetObject "System.Drawing.Pen" clr pt)
fn paletteSamplesCoords count: w: h: columns: rows: locX: locY: spaceBtw: =
(
local cnt = 1, start = 0, resultArr = #()
local cntArr = for n in 1 to rows-1 collect n*columns
for i in 1 to count do
(
local fItm = finditem cntArr i, offX = spaceBtw*(cnt-1)
append resultArr (point2 ((locX + ((cnt-1) * w)) + offX) (locY + start)) ; cnt+=1
if fItm != 0 do (cnt = 1 ; start = (h * fItm) + (spaceBtw * fItm))
) ; resultArr
)
local C1 = (defColor 25 25 25), C2 = (defColor 220 220 220), C3 = (defColor 60 100 160), C4 = (defColor 100 140 200)
local F1 = (defFont "Swis721 Cn BT" 9)
local CRS = (dotNetClass "Cursors").Hand
local TFN = (dotNetClass "System.IO.Path").GetTempFileName()
local IMGF = (dotNetClass "System.Drawing.Imaging.ImageFormat").png
local palettePanel, paletteTextEdit
local enumClass = dotNetClass "Enum"
local colorClass = dotNetClass "System.Drawing.Color"
local kcArr = enumClass.GetNames (dotNet.getType "System.Drawing.KnownColor")
local clrNameArr = for i in kcArr.count-7 to 28 by -1 collect (colorClass.FromName kcArr[i])
local clrCoordsArr = paletteSamplesCoords count:clrNameArr.count w:16 h:16 columns:10 rows:14 locX:0 locY:0 spaceBtw:1
local rgbValues = " R: 0 G: 0 B: 0"
fn paletteFormBG form arrN: arrC: =
(
local fBMP = (defBitmap form.Width form.Height), fGraph = defGraphics fBMP
if (arrN == unsupplied and arrC == unsupplied) then
(
local penBorder = defPen C3 6 ; fGraph.Clear C1
fGraph.DrawRectangle penBorder form.ClientRectangle
)
else
( fGraph.Clear C1
for i in 1 to arrN.count do
(
local rectCP = (defRect (arrC[i].x) (arrC[i].y) 16 16), brushCP = (defSolidBrush arrN[i])
fGraph.SmoothingMode = fGraph.SmoothingMode.None ; fGraph.FillRectangle brushCP rectCP
)
)
fGraph.DrawImage fBMP (defRect 0 0 fBMP.Width fBMP.Height)
fBMP.Save TFN IMGF ; fGraph.Dispose() ; deletefile TFN ; fBMP
)
fn palettePanelMD s e =
(
local pnlImg = palettePanel.BackgroundImage
local pltColor = pnlImg.GetPixel e.X e.Y
format "R = % ; G = % ; B = %
" pltColor.r pltColor.g pltColor.b
--paletteTextEdit1.Text = (substituteString (pltColor.ToString()) "A=255, " "") -- USE THIS IF YOU WANT TO SEE ONLY RGB VALUE
--N O T E :
--paletteTextEdit1.Text = ((pltColor.ToKnownColor()).ToString()) --THIS IS NOT WORK I DON'T KNOW WAY. BUT WORKS WITH "BUTTONS_PALETTE" ANYWAY :)
--USING THE NEXT FUNCTION YOU HAVE 99.9999% MATCHING
fn matchedColorName clrArr clr match:0.93 =
(
fn calculate clrArr clr match =
(
local results = #()
for i in 1 to clrNameArr.count do
(
local diff_R = 1 - ((distance [clr.r , clr.r , clr.r] [clrArr[i].r , clrArr[i].r , clrArr[i].r])/(length [255,255,255]))
local diff_G = 1 - ((distance [clr.g , clr.g , clr.g] [clrArr[i].g , clrArr[i].g , clrArr[i].g])/(length [255,255,255]))
local diff_B = 1 - ((distance [clr.b , clr.b , clr.b] [clrArr[i].b , clrArr[i].b , clrArr[i].b])/(length [255,255,255]))
if (diff_R >= match and diff_G >= match and diff_B >= match) do (append results i)
) ; results
)
local firstPass = (calculate clrArr clr match).count
local newResult = case of (
(firstPass == 0): (calculate clrArr clr (match-0.03))
(firstPass == 1): (calculate clrArr clr (match))
(firstPass == 2): (calculate clrArr clr (match+0.02))
(firstPass > 2): (calculate clrArr clr (match+0.06))
)
local idx = if newResult.count != 0 do newResult[1]
if idx != undefined then return ((clrNameArr[idx].ToKnownColor()).ToString()) else idx
)
local clrName = matchedColorName clrNameArr pltColor
if clrName != undefined then paletteTextEdit.Text = clrName else paletteTextEdit.Text = " "
)
fn defForm dnForm w h x y =
(
dnForm.ShowInTaskbar = false
dnForm.Text = " ColorPalette2"
dnForm.ClientSize = defSize w h
dnForm.StartPosition = dnForm.StartPosition.Manual ; dnForm.DesktopLocation = defPoint x y
dnForm.FormBorderStyle = dnForm.FormBorderStyle.FixedToolWindow ; dnForm.BackColor = C1
)
fn defTextEdit dxTextE w h locX locY txt active:true upper:false maxlenght:false =
(
dxTextE.Size = defSize w h
dxTextE.Location = defPoint locX locY
dxTextE.Properties.AutoHeight = false
dxTextE.BackColor = C1 ; dxTextE.ForeColor = C2
dxTextE.Text = txt ; dxTextE.Font = F1 ; dxTextE.Enabled = active
dxTextE.BorderStyle = dxTextE.BorderStyle.Simple
dxTextE.Properties.Appearance.BorderColor = C3
dxTextE.Properties.Appearance.TextOptions.HAlignment = dxTextE.Properties.Appearance.TextOptions.HAlignment.Center
if upper == true do (dxTextE.Properties.CharacterCasing = dxTextE.Properties.CharacterCasing.Upper)
if maxlenght == true do (dxTextE.Properties.MaxLength = 6)
)
paletteForm = dotNetObject "Form" ; defForm paletteForm 186 280 50 110 ; paletteForm.BackgroundImage = (paletteFormBG paletteForm)
paletteTextEdit = dotNetObject "DevExpress.XtraEditors.TextEdit" ; defTextEdit paletteTextEdit 170 20 8 253 " " active:false
palettePanel = dotNetObject "Panel" ; palettePanel.Location = defPoint 8 10 ; palettePanel.Size = defSize 169 237 ; palettePanel.backColor = C1 ;
palettePanel.BackgroundImageLayout = palettePanel.BackgroundImageLayout.Center
palettePanel.BackgroundImage = (paletteFormBG palettePanel arrN:clrNameArr arrC:clrCoordsArr)
dotNet.addEventHandler palettePanel "MouseHover" (fn palettePanelMH s e = (s.Cursor = (dotNetClass "Cursors").Cross))
dotNet.addEventHandler palettePanel "MouseLeave" (fn palettePanelML s e = (s.Cursor = (dotNetClass "Cursors").Arrow))
dotNet.addEventHandler palettePanel "MouseDown" palettePanelMD
paletteForm.Controls.addRange #(palettePanel, paletteTextEdit)
local sysPointer = dotNetObject "System.IntPtr" (windows.getMaxHWND())
local maxHandle = dotNetObject "maxCustomControls.win32HandleWrapper" sysPointer
paletteForm.Show maxHandle
)
Look the line 107 in second script and corrects spaces between letters [color=YellowGreen]HAlignment[/color]
Tested and works in max2011x64 and above.
You should have it copy the RGB values to clipboard so users could paste them in color slots.
This two scripts are only the part of other script that recive RGB value.
But i need better way than this. My method is slow.
Maybe treelist is solution, but i don’t know.
What I meant, every cell of total 140 need to have different beckcolor
what do you mean by slow? is it slow to make a dialog? how slow is it? 1 sec? 2 secs? who cares? i think that to make nice and functional dialog for 2 seconds is OK.
is it a minute? no. how slow is it? 2-3 secs are absolutely fine. don’t fool yourself.
Hi Pete,
I realy like your color palette, but VStudio and C# is my weak spot. I have no experience with programing languages. Another good but old examle is this MXS color palette
ACP (Alternate Color Picker) and Color Palette
the most important part of this kind of chat is the right sorting… i’ve tried to open a challenge to find the best way of sorting colors. unfortunately it was not interested the community.
Pete,
you have the sorting by name option but you don’t show color name in your new UI. honestly it doesn’t make sense for me. especially for system colors…
so… my concept for .NET color picker:
#1 the cool looking interface
#2 the list of smart sorting algorithms
#3 finding the best color match by picking from screen
#4 sorting by distance to the preferred color
…
any other ideas?
Pete,
the FlowLayoutPanel doesn’t have a sort method… do you have any idea how to implement it without a global overwriting?
Sorry Denis I do not want to bother you with this, but may I send you the main script which use this palette, need your opinion nothing else. (just to test.)
Script have multiple files and 80% finished code.
For that reason i don't want to post files here jet.
it fulfills the rules that are stated, especially the first
Please
i’m always open to answer any public question… it doesn’t bother me at all. it feeds me by new ideas and finally helps me make my own tools better. sometimes i appreciate your questions more than you appreciate my humble answers.
Denis, if you try this tool you’ll see what people do in VS but i try to do in MXS.
I talking about script interface. It’s unusual obviously, but not perfect of course.
:hmm: