Pchełki VBA, odcinek 14: Kolorki

https://xpil.eu/jcbIU

Dzisiejsza pchełka będzie pchełką wśród pchełek, czyli maleństwo. Zaledwie dwanaście linii kodu.

Pokażę w jaki sposób odczytać programowo kolor zadanego piksela na ekranie. Umiejętność raczej rzadko potrzebna, ale nigdy nic nie wiadomo. A nuż ktoś kiedyś będzie potrzebował odczytać kolor piksela - i bang, oto jest.

Zaczynamy. Najpierw kod, potem wyjaśnienia.

Kod:

Option Explicit

Private Declare Function GetPixel Lib "gdi32" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long) As Long
Private Declare Function GetWindowDC Lib "user32" (ByVal hwnd As Long) As Long

Sub Pchelka()
    Dim Ekran As Long, x As Long, y As Long, px As Long
    Ekran = GetWindowDC(0)
    x = Range("A1").Value
    y = Range("A2").Value
    px = GetPixel(Ekran, x, y)
    Range("A3").Value = px
    Range("A3").Interior.Color = px
End Sub

Wyjaśnienia:

Option Explicit

Wiadomo, proszę zajrzeć do poprzednich pchełek.

Private Declare Function GetPixel Lib "gdi32" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long) As Long
Private Declare Function GetWindowDC Lib "user32" (ByVal hwnd As Long) As Long

Tego typu konstrukcja już się wcześniej pojawiła - proszę pogmerać w poprzednich pchełkach. Przypominam, jest to sposób na skorzystanie z zewnętrznej, systemowej biblioteki w naszym kodzie. W tym przypadku biblioteką tą jest gdi32 (siedzi ona w pliku C:WindowsSystem32gdi32.dll), a importowane funkcje to GetPixel oraz GetWindowDC. Pierwsza zwraca kolor piksela o podanych współrzędnych (przy zadanym konteście), druga zaś zwraca kontekst urządzenia (o kontekstach za wiele tłumaczył nie będę, w wielkim skrócie: każda procedura lub funkcja biblioteki gdi32 operująca na obiekcie graficznym potrzebuje kontekstu, w którym operacja ma się odbyć).

Dalej już łatwo. Procedurę nazywamy Pchelka, a w środku:

Dim Ekran As Long, x As Long, y As Long, px As Long

Tutaj deklarujemy kilka zmiennych: Ekran to kontekst bieżącego ekranu (a dokładniej mówiąc pierwszego monitora, jeżeli mamy więcej niż jeden), x i y to współrzędne piksela na ekranie, a px to kolor piksela, wyrażony w RGB.

Ekran = GetWindowDC(0)

Tu do zmiennej Ekran wczytujemy identyfikator kontekstu pierwszego monitora (parametr 0 zawsze oznacza pierwszy monitor).

x = Range("A1").Value
y = Range("A2").Value

Tu wczytujemy współrzędne piksela do zmiennych x i y. Proszę wpisać jakieś nieduże liczby w komórki A1 oraz A2. Na przykład 100 i 100.

px = GetPixel(Ekran, x, y)

Tutaj odbywa się magia właściwa, czyli odczytujemy kolor piksela o współrzędnych x i y oraz zapisujemy go do zmiennej px.

Range("A3").Value = px
Range("A3").Interior.Color = px

Na koniec zapisujemy wartość odczytanego przed chwilą koloru do komórki A3 a także ustawiamy tło tej komórki na tenże kolor.

Jeszcze odrobina wyjaśnienia jak działa RGB. RGB to skrót od Red - Green - Blue, czyli trzech składowych podstawowych każdej barwy (a konkretniej mówiąc każdej barwy w palecie RGB, bo są jeszcze inne palety). Każda ze składowych może przyjąć jedną z wartości od 0 do 255. RGB(0,0,0) to czerń, RGB(255,255,255) to biel. RGB(255,0,0) to mocna czerwień i tak dalej.

No dobrze, ale tutaj zmienna px przyjmuje jedną wartość liczbową, a RGB wymaga trzech. O co więc chodzi?

Ano, prosta sprawa. pojedyncza składowa jest ośmiobitowa (na ośmiu bitach możemy zapisać dowolną wartość całkowitą od 0: 00000000 do 255: 11111111). W VBA typ Long jest 32-bitowy a więc pojedyncza wartość może śmiało pomieścić trzy wartości ośmiobitowe i jeszcze zostanie trochę miejsca na miotłę i kosz na brudną bieliznę.

Ponumerujmy sobie te 32 bity od zera do 31:
33222222 22221111 11111100 00000000
10987654 32109876 54321098 76543210

00000000 00000000 00000000 00000000

(kolejne dwucyfrowe numery pozycji zapisałem w pionie: 31, 30, 29, 28 i tak dalej aż do 02, 01 00)

R jest w tych 32 bitach reprezentowane przez bity 16-23, G siedzi w grupie 8-15 a B w najmłodszych ośmiu bitach (0-7). Najstarsze bity (24-31) są niewykorzystane (a konkretnie są wykorzystane dla niektórych specjalnych systemowych wartości kolorów, ale o tym może kiedy indziej).

Jeżeli więc mamy RGB(0,0,10), wartość Long będzie 10. Dla RGB(0,10,0) wartość Long będzie 10 * 256 = 2560. Wreszcie dla RGB(10,0,0) będzie to 10*256*256=655360. Jak widać, trzeba przesunąć (binarnie) wartość R o szesnaście bitów w lewo, a G o osiem bitów. Po więcej szczegółów zapraszam na Google 😉

https://xpil.eu/jcbIU

Leave a Comment

Komentarze mile widziane.

Jeżeli chcesz do komentarza wstawić kod, użyj składni:
[code]
tutaj wstaw swój kod
[/code]

Jeżeli zrobisz literówkę lub zmienisz zdanie, możesz edytować komentarz po jego zatwierdzeniu.