Color dialog

0

Planuje napisać program, który pozwala użytkownikowi wybrać kolor. Zauważyłem, że istnieje komponent colorDialog. Czy można w jakiś sposób zapożyczyć sposób szukania kolorów niestandardowych?
Interesuje mnie ta część:

user image

Można skopiować klasę ColorDialog i edytować budowę tego okna, tworząc swoja, indywidualną klasę?

0

ewentualnie, jak wygenerować klasą graphics taki panel z cała paletą barw niestandardowych.

0

Teoretycznie możesz zedytować taką kontrolkę / okno dodając własne elementy, ale praktycznie prościej będzie napisać takie coś od nowa.

Nie znam się na grafice, wszystko, co zastosowałem to zwykła interpolacja liniowa.

public static Bitmap CreateColorMap(int width, int height, Color[] gradients, Color bottom)
{
    Bitmap map = new Bitmap(width, height);

    for (int x = 0; x < width; x++)
    {
        for (int y = 0; y < height; y++)
        {
            Color fullColor = InterpolateGradient(gradients, x, width / (gradients.Length - 1));
            map.SetPixel(x, y, InterpolateColor(fullColor, bottom, y, height));
        }
    }

    return map;
}

public static int Interpolate(int from, int to, int position, int max)
{
    return (to - from) * position / max + from;
}

public static Color InterpolateColor(Color from, Color to, int position, int max)
{
    return Color.FromArgb(Interpolate(from.R, to.R, position, max),
        Interpolate(from.G, to.G, position, max),
        Interpolate(from.B, to.B, position, max));
}

public static Color InterpolateGradient(Color[] gradients, int position, int gradientWidth)
{
    int from = position / gradientWidth;
    int to = ((from + 1) == gradients.Length) ? from : from + 1;

    return InterpolateColor(gradients[from], gradients[to], position - (from * gradientWidth), gradientWidth);
}

I korzystasz z tego tak:

Color[] gradients = new Color[]
{
    Color.FromArgb(255, 0, 0),
    Color.FromArgb(255, 255, 0),
    Color.FromArgb(0, 255, 0),
    Color.FromArgb(0, 255, 255),
    Color.FromArgb(0, 0, 255),
    Color.FromArgb(255, 0, 255),
    Color.FromArgb(255, 0, 0)
};

Bitmap b = CreateColorMap(500, 200, gradients, Color.FromArgb(127, 127, 127));

Aha - uprzedzając wypowiedzi, jest to kod niezoptymalizowany, poglądowy. Do jednego wygenerowania może być okej, ale i tak użyj wskazówek ludzi mądrzejszych od nas ;): https://codeguru.pl/forum-posts-17845-2.aspx

0

Wow. O takie coś chodziło.

  1. Zapytałem się jak zedytować kontrolke, ponieważ będę potrzebował wartości RGB dla wybranego pixela. Jak mogę wyciągnąć wartość RGB pixela na podstawie koordynatów bitmapy?

  2. W jaki sposób mogę zedytować kontrolke ColorDialog?

0

Ad. 1. Odwróć wzory w metodach ;).

Ad. 2. Np. tak jak wyjaśnione jest to tutaj: http://www.codeguru.com/csharp/csharp/cs_controls/custom/article.php/c12801__2/

0

Tak się zastanawiam czy nie łatwiej po prostu wygenerować ten obrazek w sposób dowolny, zapisać jako bitmapę, a później pokazywać na PictureBox? Po kliknięciu wystarczy pobrać kolor jednego piksela, a do tego zdecydowanie nie warto wchodzić w unsafe...

0
Hass napisał(a)

a do tego zdecydowanie nie warto wchodzić w unsafe...

Ponieważ?

0
somekind napisał(a)
Hass napisał(a)

a do tego zdecydowanie nie warto wchodzić w unsafe...

Ponieważ?

Może wyraziłem się niejasno...

Hass napisał(a)

Tak się zastanawiam czy nie łatwiej po prostu wygenerować ten obrazek w sposób dowolny, zapisać jako bitmapę, a później pokazywać na PictureBox? Po kliknięciu wystarczy pobrać kolor jednego piksela, a do tego [konkretnego zastosowania] zdecydowanie nie warto wchodzić w unsafe...

Przy przetwarzaniu całych bitmap unsafe jest raczej niezbędny. Tyle tylko że tutaj nie trzeba przetwarzać całych bitmap.

0

A ile, połowę ;)?

Można zapisać to jako obrazek i później go wyświetlać oraz pobierać kolor na jego podstawie, ale są dwie wady takiego rozwiązania. Pierwszy to konieczność przechowywania takiego obrazka. Druga to dokładność. Albo przechowujemy czystą bitmapę albo skompresowanego jpega i narażamy się na kwiatki w postaci zniekształconych kolorów.

Drugi problem można wyeliminować pobierając kolor nie z obrazka, a ze wzoru, który służy do generacji takiej bitmapy.

I mimo wszystko uważam, że generowanie takiej bitmapy za każdym razem też nie będzie złym rozwiązaniem. I nie musimy używać wskaźników (dalej nie wiemy jakie są według ciebie wady ich używania ;)), bo wydajność będzie wystarczająca używając innych metod wymienionych w temacie na codeguru, a nawet SetPixel.

0
Rev.pl napisał(a)

Można zapisać to jako obrazek i później go wyświetlać oraz pobierać kolor na jego podstawie, ale są dwie wady takiego rozwiązania. Pierwszy to konieczność przechowywania takiego obrazka. Druga to dokładność. Albo przechowujemy czystą bitmapę albo skompresowanego jpega i narażamy się na kwiatki w postaci zniekształconych kolorów.

Nie ma mowy o żadnym jpg. Przechowywanie 200KB obrazka nie jest chyba kwestią problematyczną... No ale racja, można wygenerować go raz i później korzystać z bitmapy w pamięci.

Rev.pl napisał(a)

I nie musimy używać wskaźników (dalej nie wiemy jakie są według ciebie wady ich używania ;)), bo wydajność będzie wystarczająca używając innych metod wymienionych w temacie na codeguru, a nawet SetPixel.

Zapewne wszyscy znamy konsekwencje używania wskaźników, ale proszę:

  • narażamy się na błędy dostępu/zapisu nie tej pamięci, o którą nam chodziło
  • kod jest mniej czytelny i trudniejszy do debugowania (generalnie "niedotnetowy")
  • przełącznik allow unsafe code uniemożliwi odpalenie aplikacji na frameworku, którego konfiguracja nie lubi unsafe
0
Hass napisał(a)
  • narażamy się na błędy dostępu/zapisu nie tej pamięci, o którą nam chodziło

No tak, ale to odkryjemy już po jednym teście danej metody.

  • kod jest mniej czytelny i trudniejszy do debugowania (generalnie "niedotnetowy")

Ale wystarczy go raz dobrze zdebugować :)

  • przełącznik allow unsafe code uniemożliwi odpalenie aplikacji na frameworku, którego konfiguracja nie lubi unsafe

Możesz rozwinąć?

0

Ale po co rzeźbić nowe okno, skoro właśnie OD TEGO jest gotowy systemowy dialog wyboru koloru?

0
  • narażamy się na błędy dostępu/zapisu nie tej pamięci, o którą nam chodziło
  • kod jest mniej czytelny i trudniejszy do debugowania (generalnie "niedotnetowy")

No wiesz, to już kwestia twojej wiedzy i umiejętności.

A ja wciąż nie rozumiem dlaczego framework może nie "lubić" sekcji unsafe ;). Które swoją drogą są właśnie dlatego bezpieczne, bo konkretnie je oznaczamy. Kod dobrze napisany nie ma prawa wykonać się źle. Zwłaszcza, że w tym wypadku to raptem parę linijek.

Ale po co rzeźbić nowe okno, skoro właśnie OD TEGO jest gotowy systemowy dialog wyboru koloru?

Chodzi o jego rozwinięcie. Domyślnie .NET Framework nie pozwala na to, trzeba przechwytywać komunikaty i tworzyć kontrolki w WinApi, co nie będzie zbyt wygodnym rozwiązaniem.

0

Samo słowo "unsafe" oznacza, że kod nie jest bezpieczny, a nie że jest niebezpieczny (ang. dangerous).

W niektórych miejscach (procedury składowane SQL, Silverlight, ...) sekcje unsafe są niedozwolone. Ale nie ma nic złego w używaniu ich np. w aplikacjach okienkowych.

Jakiś czas temu pisałem program wyświetlający grafikę na PictureBox-ie; operowanie wskaźnikami i bezpośrednie "mazanie" po pamięci było ze 50% szybsze od metody "kulturalnej". A jak coś schrzanisz to i tak i tak poleci wyjątek, tylko w jednym przypadku będzie to "index out of bounds" a w drugim mniej szczegółowe "access violation".

1 użytkowników online, w tym zalogowanych: 0, gości: 1