投稿者 魔界の仮面弁士  (社会人) 投稿日時 2021/6/6 18:39:36
> こんばんは魔界の弁士様。
> こんばんは、魔界の仮面弁士様
> おはようございます。魔界の弁士様。
> こんにちは、魔界の仮面弁士様

「魔界の仮面弁士」です…。

回答が遅くなりました。
沢山投稿していただいたので、順に回答していきます。


[2021/6/5 16:53:14]への返信
> VBAのピクセルの色で質問があります。
Excel ワークシートの色ということなので、
ここでいう VBA とは、Excel の VBA という事で良いのですよね。

質問時には明記されていませんでしたが、お使いの Office バージョンは何ですか?
https://support.microsoft.com/ja-jp/office/932788b8-a3ce-44bf-bb09-e334518b8b19?WT.mc_id=DT-MVP-8907&ui=ja-JP&rs=ja-JP&ad=JP

2010 以降かつ 32bit 版であろうという点までは推察できますが、手元の環境は
64bit 版なので、頂いたコードを手直ししないとコンパイルすら通らないです…。


凡例:🔸サポート期限切れ/🔷サポート期間内

🔸Office 2007 … 32bit 版のみ
🔸Office 2010 … 32bit/64bit 版の 2種類(通常は 32bit 版がインストールされる)
 条件付き定数 VBA7 と Win64 、PtrSafe キーワードなどが追加された最初のバージョン。
🔷Excel 2012/2013/2016 … 32bit/64bit 版の 2種類が存在。
 特に指定しなければ 32bit 版がインストールされる。
🔷Excel 2019 (現行の 365) … 32bit/64bit 版の 2種類が存在。
 特に指定しなければ 64 bit 版がインストールされる。



[2021/6/5 23:22:48]への返信
> hwnd = WindowFromPoint(0, 0)
> hdc = GetDC(hwnd)
> If hdc = 0 Then
> MsgBox "失敗しました。"
> Else
取得失敗を判定するなら、Exit Sub するなり Err.Raise するなりした方が良いでしょう。
今のコードだと、hdc の取得が失敗したときにも処理を続行して、
GetPixel や ReleaseDC を呼び出してしまいます。


で…そもそもデバイスコンテキストを取得処理に問題があります。

0,0 位置に Excel のワークシート領域があるとは限りませんし、
仮に Excel が最大化されていたとしても、
 hwnd = WindowFromPoint(0, 0)
で得られる値は、Excel VBA の Application.Hwnd プロパティと変わりません。

しかもそれはワークシート領域を指すウィンドウのハンドルではありませんし、
そこから GetDC しても、求める色は得られないでしょう。

代わりに「hDC = GetDC(ByVal CLngPtr(0))」を試してみてください。
あるいは CreateDC で "DISPLAY" のコンテキストを得るようにします。

例えばこんな感じ。[ページレイアウト]-[背景]で挿入した画像の色を取得できています。


Option Explicit
#If VBA7 Then
Private Declare PtrSafe Function CreateDCW Lib "gdi32" (ByVal pwszDriver As LongPtr, ByVal pwszDevice As LongPtr, ByVal pszPort As LongPtr) As LongPtr
Private Declare PtrSafe Function DeleteDC Lib "gdi32" (ByVal hDC As LongPtr) As Long
Private Declare PtrSafe Function GetPixel Lib "gdi32" (ByVal hDC As LongPtr, ByVal nXPos As LongByVal nYPos As LongAs OLE_COLOR
#Else
Private Declare PtrSafe Function CreateDCW Lib "gdi32" (ByVal pwszDriver As OLE_HANDLE, ByVal pwszDevice As OLE_HANDLE, ByVal pszPort As OLE_HANDLE) As OLE_HANDLE
Private Declare PtrSafe Function DeleteDC Lib "gdi32" (ByVal hDC As OLE_HANDLE) As Long
Private Declare PtrSafe Function GetPixel Lib "gdi32" (ByVal hDC As OLE_HANDLE, ByVal nXPos As LongByVal nYPos As LongAs OLE_COLOR
#End If

Public Function GetColor(x&, y&) As OLE_COLOR
#If VBA7 Then
    Dim hDC As LongPtr
    hDC = CreateDCW(StrPtr("DISPLAY"), 0, 0)
#Else
    Dim hDC As OLE_HANDLE
    hDC = CreateDCW(ByVal StrPtr("DISPLAY"), ByVal 0&, ByVal 0&)
#End If
    If 
    GetColor = GetPixel(hDC, x, y)
    DeleteDC hDC
End Function


上記はスクリーン全体が対象となるため、Excel 以外のデスクトップ領域も対象となります。
ワークシート左上の座標を取得したい場合には、A1 セルが左上に表示された状態にして
 x = ActiveWindow.PointsToScreenPixelsX(0)
 y = ActiveWindow.PointsToScreenPixelsY(0)
で求めることが出来ます。


> ⇒net(c#)では、
net ではなく .NET (ドットネット) ですよ。
ポータルサイトの URL も https://dot.net/ ですし。

また、「c#」ではなく 「C#」と書きます。
JIS X 3015 の規格 (および ECMA-334) において、次のように定められていますので。
>> C#は,“しーしゃーぷ”と発音する。 
>> C#は,LATIN CAPITAL LETTER C (U+0043)の次に NUMBER SIGN # (U+0023)を書く。 


> Alias "GetWindowTextA"
GetWindowTextW などの Wide 系 API にすることで、Shift_JIS にない文字列にも対応できます。
(Win9x 系が駆逐された今、ANSI 系 API でなければならない理由はほとんど無いはず)

> webのコードを参考に、私でも非常に簡単に出来ました。
> // ローカルファイルの場合
> bitmap = new Bitmap(fn);
そのコードは、画像ファイルの画素を取り出すものであって、肝心の
Excel ワークシート部分の画素を取り出すものではないですよね。

ワークシート部分を fn で示されたファイルに変換するためのコードはどうされましたか?