Notifications
Clear all

[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
  )
14 Replies

Cool concepts man. Nice work.
Second script does not run for me.

1 Reply
(@gazybara)
Joined: 11 months ago

Posts: 0

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.

4 Replies
(@gazybara)
Joined: 11 months ago

Posts: 0

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

(@denist)
Joined: 11 months ago

Posts: 0

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.

(@gazybara)
Joined: 11 months ago

Posts: 0

Hi Denis,
Yes it’s opens slow.

(@denist)
Joined: 11 months ago

Posts: 0

is it a minute? no. how slow is it? 2-3 secs are absolutely fine. don’t fool yourself.

Hey Branko,

I realized that my original chart was slow to build in MXS, so did some other versions using a custom control in VS. the results are here if you missed it.

3 Replies
(@gazybara)
Joined: 11 months ago

Posts: 0

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

(@denist)
Joined: 11 months ago

Posts: 0

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?

(@denist)
Joined: 11 months ago

Posts: 0

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: