C# デスクトップアイコンの数

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
アバター
記事: 58
登録日時: 10年前
住所: 大阪府

C# デスクトップアイコンの数

#1

投稿記事 by » 9年前

こんばんは。 デスクトップアイコンの数を取得するコードを書いたのですが、(ほとんどコピー)
普通はこれを実行するとデスクトップアイコンの数が表示されます。
しかし、一度壁紙を変えると、explorer.exeを再起動するまで、何度やっても「0」としか表示されなくなります。
これは何が原因でどうすれば直るのでしょうか?
僕にはまったく分からないので困っています。

環境はVisual C# 2010です。
どなたか教えてくださる方いらっしゃいますでしょうか?
よろしくお願いします。

コードです↓

コード:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {

        [DllImport("user32.dll")]
        public static extern IntPtr FindWindow(string strclassName, string strWindowName);

        [DllImport("user32", EntryPoint = "FindWindowEx")]
        public static extern IntPtr FindWindowEx(IntPtr hWnd1, IntPtr hWnd2, string lpsz1, string lpsz2);

        [DllImport("user32.dll")]
        public static extern int SendMessage(IntPtr hWnd, int wMsg, int wParam, int lParam);

        public const int LVM_GETITEMCOUNT = 0x1004;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

            IntPtr hWnd;
            hWnd = FindWindow("Progman", "Program Manager");
            hWnd = FindWindowEx(hWnd, IntPtr.Zero, "SHELLDLL_DefView", null);
            hWnd = FindWindowEx(hWnd, IntPtr.Zero, "SysListView32", null);
            int nItemCount = SendMessage(hWnd, LVM_GETITEMCOUNT, 0, 0);
            label1.Text = nItemCount.ToString();
        }
    }
}
(編集):コードタグ入力機能で言語名を入力しました。

アバター
sizuma
記事: 8
登録日時: 10年前
住所: 鹿児島

Re: C# デスクトップアイコンの数

#2

投稿記事 by sizuma » 9年前

WinAPIは分からないので、とりあえずデスクトップディレクトリを探して、ファイル数を数えるプログラムを書いてみました。
ちなみにVC#2005Expreesです。
textBox1とlistBox1,buton1,button1_Clickイベントを追加すると動くと思います

コード:

    
public partial class Form1 : Form
{
    string deskTopPath;
    int count = 0;
    public Form1()
    {
         InitializeComponent();           
     }

     private void Form1_Load(object sender, EventArgs e)
     {
            deskTopPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
            this.button1_Click(sender, e);         
      }


    private void button1_Click(object sender, EventArgs e)
   {
         count = 0;
         listBox1.Items.Clear();
         foreach (string deskFile in System.IO.Directory.GetFiles(deskTopPath))
         {
             listBox1.Items.Add(deskFile);
             count++;
          }
          foreach (string deskDir in System.IO.Directory.GetDirectories(deskTopPath))
          {
              listBox1.Items.Add(deskDir);
              count++;
          }
          textBox1.Text = count.ToString();
      }
ただの興味なんですが、何処のソースをコピペしましたか?

(編集)インデントが崩れてるけど、ま、いっか(笑

アバター
記事: 58
登録日時: 10年前
住所: 大阪府

Re: C# デスクトップアイコンの数

#3

投稿記事 by » 9年前

返信ありがとうございます!

壁紙を変えてもちゃんと動くようになりました^^
ありがとうございました。
ただの興味なんですが、何処のソースをコピペしましたか?
http://oshiete.goo.ne.jp/qa/1026496.html
ここです。
あと、厚かましいかもしれませんが、もしよければアイコンの位置を取得する方法も教えていただけませんでしょうか?
C++のコードはここhttp://7ujm.net/C++/DesktopIconPoint.htmlに載っていたのですが、
知識がないもので、まったく分かりませんでした。

出来ればでいいので、よろしくお願いします。

アバター
pooka
記事: 7
登録日時: 10年前
住所: 福井

Re: C# デスクトップアイコンの数

#4

投稿記事 by pooka » 9年前

ちょっと書いてみました。
ListBoxを追加してください。

コード:

using System;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace Sample
{
	public partial class Form1 : Form
	{
		public const uint PROCESS_VM_OPERATION = 0x8;
		public const uint PROCESS_VM_READ = 0x10;
		public const uint PROCESS_VM_WRITE = 0x20;
		public const uint MEM_RESERVE = 0x2000;
		public const uint MEM_COMMIT = 0x1000;
		public const uint PAGE_READWRITE = 0x4;
		public const int LVM_GETITEMPOSITION = 0x1010;
		public const int LVM_GETITEMCOUNT = 0x1004;
		public const uint MEM_RELEASE = 0x8000;

		[DllImport("user32.dll")]
		public static extern IntPtr FindWindow(string strclassName, string strWindowName);

		[DllImport("user32", EntryPoint = "FindWindowEx")]
		public static extern IntPtr FindWindowEx(IntPtr hWnd1, IntPtr hWnd2, string lpsz1, string lpsz2);

		[DllImport("user32.dll")]
		public static extern int SendMessage(IntPtr hWnd, int wMsg, int wParam, IntPtr lParam);

		[DllImport("user32.dll")]
		public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);

		[DllImport("kernel32.dll")]
		public static extern IntPtr OpenProcess(uint dwDesiredAccess, bool bInheritHandle, uint dwProcessId);

		[DllImport("kernel32.dll")]
		public static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);

		[DllImport("kernel32.dll")]
		public static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, IntPtr lpBuffer, int nSize, ref uint vNumberOfBytesRead);

		[DllImport("kernel32.dll")]
		public static extern bool VirtualFreeEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint dwFreeType);

		[DllImport("kernel32.dll")]
		public static extern bool CloseHandle(IntPtr hObject);

		public Form1()
		{
			InitializeComponent();
		}

		private void Form1_Load(object sender, EventArgs e)
		{
			GetIconPosition();
		}

		public static bool ListView_GetItemPosition(IntPtr hwnd, int i, IntPtr ppt)
		{
			return SendMessage(hwnd, LVM_GETITEMPOSITION, i, ppt) != 0;
		}
		public static int ListView_GetItemCount(IntPtr AHandle)
		{
			return SendMessage(AHandle, LVM_GETITEMCOUNT, 0, IntPtr.Zero);
		}

		private void GetIconPosition()
		{
			IntPtr hWnd;
			IntPtr hProcess;
			IntPtr pnt;
			Point[] iconPoint = new Point[1];
			int iconCount;
			uint dwProcessId;
			uint vNumberOfBytesRead = 0;

			hWnd = FindWindow("Progman", "Program Manager");
			hWnd = FindWindowEx(hWnd, IntPtr.Zero, "SHELLDLL_DefView", null);
			hWnd = FindWindowEx(hWnd, IntPtr.Zero, "SysListView32", null);

			//アイコンの数を取得
			iconCount = ListView_GetItemCount(hWnd);

			GetWindowThreadProcessId(hWnd, out dwProcessId);
			hProcess = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, false, dwProcessId);
			pnt = VirtualAllocEx(hProcess, IntPtr.Zero, 4096, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);

			for (int i = 0; i < iconCount; i++)
			{
				//アイコンの位置を取得
				ListView_GetItemPosition(hWnd, i, pnt);
				ReadProcessMemory(hProcess, pnt, Marshal.UnsafeAddrOfPinnedArrayElement(iconPoint, 0), Marshal.SizeOf(typeof(Point)), ref vNumberOfBytesRead);

				listBox1.Items.Add(string.Format("x:{0}, y:{1}", iconPoint[0].X, iconPoint[0].Y));
			}

			VirtualFreeEx(hProcess, pnt, 0, MEM_RELEASE);
			CloseHandle(hProcess);
		}
	}
}

これでアイコンの位置を取得できるかと思います。
ただ、壁紙を変えると取得できませんが・・・

あとsizumaさんが書かれている方法ではごみ箱などの数は含まれず、desktop.iniなどの隠しファイルが含まれてしまうので、
デスクトップアイコンの数としては少し違うかなと思います。
(自分も最初はその方法でいいのではと思ってました・・・)

アバター
記事: 58
登録日時: 10年前
住所: 大阪府

Re: C# デスクトップアイコンの数

#5

投稿記事 by » 9年前

ありがとうございます。
すごいですね! 動きましたよ。
pooka さんが書きました:ただ、壁紙を変えると取得できませんが・・・
位置の取得を教えてもらえたので、壁紙のことは今回はあきらめようかと思います。
そんなにしょっちゅう壁紙変えることもないですもんね。
pooka さんが書きました:あとsizumaさんが書かれている方法ではごみ箱などの数は含まれず、desktop.iniなどの隠しファイルが含まれてしまうので、デスクトップアイコンの数としては少し違うかなと思います。
そうでしたか。desktop.iniというファイルがあることは今まで知りませんでした。

sizumaさん、pookaさん、いろいろ教えていただいてありがとうございました。
とても勉強になりました。

pookaさんのコードは、まだ完全に理解できていないところもあるので、
もっと勉強して理解できるようにがんばります。

閉鎖

“C言語何でも質問掲示板” へ戻る