tagCANDY CGI VBレスキュー(花ちゃん) の Visual Basic 2010 用 掲示板(VB.NET 掲示板) [ツリー表示へ]   [Home]
一括表示(VB.NET VB2005)
タイトル構造体を引数とするAPI(SystemParametersInfo)
記事No9525
投稿日: 2009/10/29(Thu) 07:22
投稿者ダンボ
ListViewのタイル表示でのアイコン間隔を変えたくて、SystemParametersInfoの
SPI_GETICONMETRICS、SPI_SETICONMETRICSを利用してみました。
(SPI_ICONHORIZONTALSPACINGで得られる値は別物ですよね?)
SystemParametersInfoの第3引数にICONMETRICS構造体へのポインターを指定するらしいですが
下記コードではエラーリターンしてしまいます。
行き詰まってしまいましたのでアドバイスをよろしくお願いします。
それと第4引数を0にしておけば、このAPPだけに作用して終了後に規定値に戻ると予想して
いるのですが、当たっているでしょうか?

Imports System.Runtime.InteropServices

<DllImport("USER32.DLL")> _
Private Function SystemParametersInfo( _
    ByVal uAction As Integer, _
    ByVal uparam As Integer, _
    <[In](), Out()> ByRef lpvParam As ICONMETRICS, _
    ByVal fuWinIni As Integer _
) As Boolean
End Function
Private Const SPI_ICONHORIZONTALSPACING As Integer = 13
Private Const SPI_ICONVERTICALSPACING As Integer = 24
Private Const SPI_GETICONMETRICS As Integer = 45
Private Const SPI_SETICONMETRICS As Integer = 46
Private Const SPIF_SENDWININICHANGE As Integer = &H2
Private Const SPIF_UPDATEINIFILE As Integer = &H1

<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)> _
Structure ICONMETRICS
    Dim cbSize As Integer                              '構造体のバイト数
    Dim iHorzSpacing As Integer                        '水平方向の間隔
    Dim iVertSpacing As Integer                        '同、垂直方向
    Dim iTitleWrap As Integer                          '0のとき、キャプションを折り返さない
    Dim lfFont As LOGFONT                           'キャプションのフォントを指定するLOGFONT構造体
End Structure

Public Const LF_FACESIZE As Int32 = 32
Public Const DEFAULT_CHARSET As Byte = 1
Public Const FW_NORMAL As Int32 = 400
Public Const FIXED_PITCH As Byte = 1
Public Const OUT_RASTER_PRECIS As Byte = 6
Public Const WM_SETFONT As Int32 = &H30
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)> _
Public Structure LOGFONT
    Public lfHeight As Int32
    Public lfWidth As Int32
    Public lfEscapement As Int32
    Public lfOrientation As Int32
    Public lfWeight As Int32
    Public lfItalic As Byte
    Public lfUnderline As Byte
    Public lfStrikeOut As Byte
    Public lfCharSet As Byte
    Public lfOutPrecision As Byte
    Public lfClipPrecision As Byte
    Public lfQuality As Byte
    Public lfPitchAndFamily As Byte
    <VBFixedString(LF_FACESIZE)> Public lfFaceName As String
    Public Sub New(ByVal fontName As String)
       lfWeight = FW_NORMAL
       lfCharSet = DEFAULT_CHARSET
       lfPitchAndFamily = FIXED_PITCH
       lfOutPrecision = OUT_RASTER_PRECIS
       lfFaceName = fontName
       lfHeight = 32
    End Sub
End Structure

Public Sub main(ByVal CmdArgs() As String)
    Dim LOGFONT As New LOGFONT(Space(LF_FACESIZE))
    Dim ICONMETRICS As New ICONMETRICS
    ICONMETRICS.lfFont = LOGFONT
    ICONMETRICS.cbSize = Marshal.SizeOf(ICONMETRICS)
    If Not SystemParametersInfo(SPI_GETICONMETRICS, ICONMETRICS.cbSize, ICONMETRICS, 0) Then Stop

[ツリー表示へ]
タイトルRe: 構造体を引数とするAPI(SystemParametersInfo)
記事No9526
投稿日: 2009/10/29(Thu) 10:09
投稿者オショウ
    Private Const SPI_GETICONMETRICS As Integer = 45
    Private Const LF_FACESIZE As Int32 = 32

    <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto, Pack:=1)> _
    Private Structure LOGFONT
        Public lfHeight As Int32
        Public lfWidth As Int32
        Public lfEscapement As Int32
        Public lfOrientation As Int32
        Public lfWeight As Int32
        Public lfItalic As Byte
        Public lfUnderline As Byte
        Public lfStrikeOut As Byte
        Public lfCharSet As Byte
        Public lfOutPrecision As Byte
        Public lfClipPrecision As Byte
        Public lfQuality As Byte
        Public lfPitchAndFamily As Byte
        <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=LF_FACESIZE)> Public lfFaceName As String
    End Structure

    <StructLayout(LayoutKind.Sequential, Pack:=1)> _
    Private Structure ICONMETRICS
        Public cbSize As Int32                              '構造体のバイト数
        Public iHorzSpacing As Int32                        '水平方向の間隔
        Public iVertSpacing As Int32                        '同、垂直方向
        Public iTitleWrap As Int32                          '0のとき、キャプションを折り返さない
        Public lfFont As LOGFONT                           'キャプションのフォントを指定するLOGFONT構造体
        Public Sub New(ByVal dummy As Integer)
            lfFont = New LOGFONT
        End Sub
    End Structure

    <DllImport("USER32.DLL", CharSet:=CharSet.Auto, EntryPoint:="SystemParametersInfo", SetLastError:=True)> _
    Private Shared Function SystemParametersInfo( _
        ByVal uAction As Integer, _
        ByVal uparam As Integer, _
        <[In](), Out()> ByRef lpvParam As ICONMETRICS, _
        ByVal fuWinIni As Integer _
    ) As Boolean
    End Function

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

        Dim im As ICONMETRICS
        Dim bRet As Boolean

        im = New ICONMETRICS(0)
        im.cbSize = Marshal.SizeOf(im)

        bRet = SystemParametersInfo(SPI_GETICONMETRICS, Marshal.SizeOf(im), im, 0)

    End Sub

  こんなんで如何?

※ VISTA Ultimate で動作しました。

以上。参考まで

[ツリー表示へ]
タイトルRe: 構造体を引数とするAPI(SystemParametersInfo)
記事No9528
投稿日: 2009/10/29(Thu) 15:45
投稿者Hongliang
// 本題の回答ではありませんが。

> SPI_GETICONMETRICS、SPI_SETICONMETRICSを利用してみました。
> (SPI_ICONHORIZONTALSPACINGで得られる値は別物ですよね?)
iHorzSpacing および iVertSpacing に関しては同じです。
そして、これらは ListView の View.LargeIcon のみに影響する値のはずです。

> それと第4引数を0にしておけば、このAPPだけに作用して終了後に規定値に戻ると予想して
いるのですが、当たっているでしょうか?
この関数はシステム全体の設定を変更するものです。
また、特に戻ると言うこともありません。

[ツリー表示へ]
タイトル[解決]構造体を引数とするAPI(SystemParametersInfo)
記事No9532
投稿日: 2009/10/29(Thu) 22:41
投稿者ダンボ
オショウ さん、Hongliang さん、どうもありがとうございます。

オショウ さんのコードで動作しました。私のコードのどこが悪いのかを色々検証しました。
まず致命的だったのが
    Dim LOGFONT As New LOGFONT(Space(LF_FACESIZE))
    Dim ICONMETRICS As New ICONMETRICS
    ICONMETRICS.lfFont = LOGFONT
のように構造体を2つ論理的につなげたことであり、物理的につながっていませんでした。
このためMarshal.SizeOf(im)がオショウ さんのコードでは108、私のコードでは48でした。
「物理的に連続」ということが重要だったんですね。もう一つ意外だったのは、
<DllImport("USER32.DLL", CharSet:=CharSet.Auto)>Private Function SystemParametersInfo(...
では動作し、
<DllImport("USER32.DLL")>Private Function SystemParametersInfo(...
ではエラーリターンしたことです。構造体データ中に文字列があるからでしょうか。

> > SPI_GETICONMETRICS、SPI_SETICONMETRICSを利用してみました。
> > (SPI_ICONHORIZONTALSPACINGで得られる値は別物ですよね?)
> iHorzSpacing および iVertSpacing に関しては同じです。
> そして、これらは ListView の View.LargeIcon のみに影響する値のはずです。

はい、同じ値でした。実は画面のプロパティ→デザイン詳細→アイコンの間隔(横)=46、
アイコンの間隔(縦)=43という値を得たかったのですが、iHorzSpacing =78、iVertSpacing =75でした。
どうやら画面のプロパティで示す値は32×32アイコンを前提としている感じです。

> > それと第4引数を0にしておけば、このAPPだけに作用して終了後に規定値に戻ると予想して
> いるのですが、当たっているでしょうか?
> この関数はシステム全体の設定を変更するものです。
> また、特に戻ると言うこともありません。

そのとおりでした。APP終了前に元の設定値に戻しておかねば。。。
Private Const SPIF_UPDATEINIFILE As Integer = &H1
これが立っていなければ、システム再起動で元の値に戻るってことですよね。

[ツリー表示へ]