- PR -

FromHandleで生成したIconをSaveしたとき

投稿者投稿内容
ぐるうぶ
会議室デビュー日: 2006/01/31
投稿数: 5
投稿日時: 2006-01-31 21:26
お世話になります。

VB2005でFromHandleメソッドで生成したIconをSaveメソッドで保存すると
アイコンが変化してしまうので困っています。

コード:


Public Class Form1

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

Dim icon1 As New Icon("C:\Program Files\Microsoft Visual Studio 8\Setup\setup.ico")
Dim icon2 As Icon = Drawing.Icon.FromHandle(icon1.Handle)

Using fs As New IO.FileStream("C:\icon1.ico", IO.FileMode.Create)
icon1.Save(fs)
fs.Close()
End Using
Using fs As New IO.FileStream("C:\icon2.ico", IO.FileMode.Create)
icon2.Save(fs)
fs.Close()
End Using

End Sub

End Class


元のアイコン(icon1)は32bitカラーで48×48,32×32,16×16の3つのイメージで
Saveしてもそのまま保存されるのですが、
FromHandleで生成したアイコン(icon2)はSaveすると
16色で32×32のイメージ1つだけになってしまいます。
どうしたら元のアイコンをそのまま保存できるのでしょうか。

本当はExtractIconExなどのAPIで取得したhIconからアイコンを保存したいんですが、
現象を分かりやすくするために上記のコードを書きました。
よろしくお願いします。

[ メッセージ編集済み 編集者: ぐるうぶ 編集日時 2006-01-31 21:37 ]
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2006-02-01 09:32
引用:

ぐるうぶさんの書き込み (2006-01-31 21:26) より:

VB2005でFromHandleメソッドで生成したIconをSaveメソッドで保存すると
アイコンが変化してしまうので困っています。


FromHandle メソッドは、おそらく CopyIcon 関数にあたるのだと思います。
完全に複製されるわけではない (アルファ ブレンドの情報を持たない) のでしょう。

.NET Framework 1.1 でも多分そうです。

引用:

どうしたら元のアイコンをそのまま保存できるのでしょうか。


完全な複製である DuplicateIcon 関数にあたる、Clone メソッドで解決できると思います。

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
ぐるうぶ
会議室デビュー日: 2006/01/31
投稿数: 5
投稿日時: 2006-02-01 10:46
じゃんぬねっとさん、返答ありがとうございます。

引用:

じゃんぬねっとさんの書き込み (2006-02-01 09:32) より:

完全な複製である DuplicateIcon 関数にあたる、Clone メソッドで解決できると思います。


どうも、やりたいことが伝わっていないようですね。
現象を分かりやすくと思って書いたコードが仇になったでしょうか(^_^;
Iconオブジェクトを複製したいのではなく

引用:

本当はExtractIconExなどのAPIで取得したhIconからアイコンを保存したいんですが、


なので、Cloneメソッドは使えないです。
http://www.atmarkit.co.jp/fdotnet/dotnettips/280getappicon/getappicon.html
の様なことをやっていて(ここではSHGetFileInfoを使ってますが)
このサンプルでいうとappIconをSaveメソッドで保存すると16色アイコンになってしまうんです。
どうやったら32bitカラーで保存できるのでしょうか?
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2006-02-01 12:16
引用:

ぐるうぶさんの書き込み (2006-02-01 10:46) より:

どうも、やりたいことが伝わっていないようですね。
現象を分かりやすくと思って書いたコードが仇になったでしょうか(^_^;


うわ、すいません。(*_ _)

引用:

どうやったら32bitカラーで保存できるのでしょうか?


HICON では生データは扱えませんので、GetDIBits 関数などを使って HBITMAP から取得するしかないでしょうね。
で、HBitmap から ImageFormat.Icon として保存... できるかなぁ。

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
Tdnr_Sym
ぬし
会議室デビュー日: 2005/09/13
投稿数: 464
お住まい・勤務地: 明石・神戸
投稿日時: 2006-02-01 12:55
こんにちは。

引用:

ぐるうぶさんの書き込み (2006-02-01 10:46) より:

Iconオブジェクトを複製したいのではなく
引用:

本当はExtractIconExなどのAPIで取得したhIconからアイコンを保存したいんですが、


なので、Cloneメソッドは使えないです。



たぶんExtractIconExじゃ、実行可能ファイルのリソースから
元々のicoファイルを抜き出せないんじゃないでしょうか。
ExtractIconExは大きいアイコンと小さいアイコンだけしか抽出できないですが、
アイコンリソース(RT_ICONGROUPとRT_ICONの組み合わせ)やicoファイルは複数のイメージを保持しています。

私が以前この掲示板で、icoファイルを実行可能ファイルのリソースとして挿入するサンプルプログラムを
投稿していますが↓
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?mode=viewtopic&topic=26073&forum=7&start=16

原理的にはその逆を行えば、実行可能ファイルのアイコンリソースからicoファイルを抜き出すことができると思います。

アイコンリソースやicoファイルのフォーマットを調べてもらえば分かると思いますが、
複数のイメージデータとそれらを管理するディレクトリ情報で構成されています。

たぶんhIconハンドルは1つのイメージデータだけしか管理していないと思います。
ぐるうぶ
会議室デビュー日: 2006/01/31
投稿数: 5
投稿日時: 2006-02-01 16:41
じゃんぬねっとさん、Tdnr_Symさん、ありがとうございます。
引用:

じゃんぬねっとさんの書き込み (2006-02-01 12:16) より:

HICON では生データは扱えませんので、GetDIBits 関数などを使って HBITMAP から取得するしかないでしょうね。
で、HBitmap から ImageFormat.Icon として保存... できるかなぁ。


海外のサイトに似たようなことをしているサンプルコードがあったので、それを参考にやってみました。
大まかに言うとCreateDIBitsして、そこにカラーイメージとマスクイメージをDrawIconExして、
そのイメージをそのまま.icoフォーマットに埋め込むという感じです。
じゃんぬさんの意図していることと同じかどうか分かりませんが、32bitカラーで保存できました。(^_^)
元のコードがC#で256色アイコン用だったのを色々いじって
32bitカラー用に変えただけなので、これからVBで清書します。
32bitカラー決め打ちで汎用性がないのがアレですが…

引用:

Tdnr_Symさんの書き込み (2006-02-01 12:55) より:

アイコンリソースやicoファイルのフォーマットを調べてもらえば分かると思いますが、
複数のイメージデータとそれらを管理するディレクトリ情報で構成されています。

たぶんhIconハンドルは1つのイメージデータだけしか管理していないと思います。


やはり海外のサイトにEXEやDLLのアイコンリソースを取得して.icoフォーマットに変換する
C#のサンプルコードがあったので、やろうと思えばできるでしょうが
今はhIconから取得できる1つのイメージが変換できればいいのでBitmap経由で行きたいと思います。

ところでC#でUnmanagedを扱うときによく見るunsafeやfixedというのは
VBに移植するときには何か考慮する必要があるのでしょうか?もし分かれば教えてください。
Hongliang
ぬし
会議室デビュー日: 2004/12/25
投稿数: 576
投稿日時: 2006-02-01 17:16
引用:

ぐるうぶさんの書き込み (2006-02-01 16:41) より:

ところでC#でUnmanagedを扱うときによく見るunsafeやfixedというのは
VBに移植するときには何か考慮する必要があるのでしょうか?もし分かれば教えてください。


そもそもVBでは unsafe コンテキストを扱えません。
ポインタを操作する場合、System.Runtime.InteropServices 名前空間の Marshal クラスを使用してアクセスする必要があります。
個人的にそう差は無いと思ってますが、ネックは構造体を操作するのが面倒になる点ですかね。


引用:

じゃんぬねっとさんの書き込み (2006-02-01 12:16) より:

で、HBitmap から ImageFormat.Icon として保存... できるかなぁ。


.NET2.0までじゃ ImageFormat.Icon によるImage.Saveはサポートされてませんねー。
例外も吐かずに黙って png で保存してくれます。
// 私の環境では png だけどそうとも限らないのかな?
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2006-02-01 17:42
引用:

Hongliangさんの書き込み (2006-02-01 17:16) より:

.NET2.0までじゃ ImageFormat.Icon によるImage.Saveはサポートされてませんねー。
例外も吐かずに黙って png で保存してくれます。


そうですか、やはり Icon には戻せないのですね。

引用:

// 私の環境では png だけどそうとも限らないのかな?


実は試してはいないわけですがw
おそらくどの環境でもそうなるだろうと思います。
やはり、もっと低レベルなところで変換させるしかなさそうですね。

# 最初に頓珍漢なレスを返したために、やむなく提示した方法でした...

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌

スキルアップ/キャリアアップ(JOB@IT)