我是新手,
最近尝试编写一个日历但是,不知道如何让日历始终显示在桌面上。
系统:win7 64位
版本:visual studio 2012要求:
1.日历不要求:始终在最前端。因为这个功能很容易实现,窗体选项中有这个。
2.按“显示桌面”的时候,日历不被隐藏。备注:网上找了好几种方法,都不好使,比如:
        [DllImport("user32.dll")]
        public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
        [DllImport("user32.dll")]
        public static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
            IntPtr hWndNewParent = FindWindow("Progman", "Program Manager");
            SetParent(this.Handle, hWndNewParent);
这种方法,在win7系统不好用,日历窗体变成透明的了。看不见。非常感谢各位大大。帮帮小弟。

解决方案 »

  1.   

    Program Manger ?  是个啥?
    我记得桌面是 "SysListView32"我也是win7系统 以前做实验的时候想桌面 嵌入过 也没有啥问题
      

  2.   

    用spy++找桌面,然后set parent 到桌面,xp,win7,win8都做过
    private void Window_Loaded(object sender, RoutedEventArgs e) {
    IntPtr desktopHwnd = GetDesktopPtr();
    IntPtr ownHwnd = new WindowInteropHelper(this).Handle;
    IntPtr result = Win32.SetParent(ownHwnd, desktopHwnd);
    }private IntPtr GetDesktopPtr() {
    // http://blog.csdn.net/mkdym/article/details/7018318
    // 情况一
    IntPtr hwndWorkerW = IntPtr.Zero;
    IntPtr hShellDefView = IntPtr.Zero;
    IntPtr hwndDesktop = IntPtr.Zero;
    IntPtr hProgMan = Win32.FindWindow("ProgMan", null);
    if (hProgMan != IntPtr.Zero) {
    hShellDefView = Win32.FindWindowEx(hProgMan, IntPtr.Zero, "SHELLDLL_DefView", null);
    if (hShellDefView != IntPtr.Zero) {
    hwndDesktop = Win32.FindWindowEx(hShellDefView, IntPtr.Zero, "SysListView32", null);
    }
    }
    if (hwndDesktop != IntPtr.Zero) return hwndDesktop; // 情况二
    //必须存在桌面窗口层次
    while (hwndDesktop == IntPtr.Zero) {
      //获得WorkerW类的窗口
      hwndWorkerW = Win32.FindWindowEx(IntPtr.Zero, hwndWorkerW, "WorkerW", null);
      if (hwndWorkerW == IntPtr.Zero) break;
      hShellDefView = Win32.FindWindowEx(hwndWorkerW, IntPtr.Zero, "“SHELLDLL_DefView", null);
      if (hShellDefView == IntPtr.Zero) continue;
      hwndDesktop = Win32.FindWindowEx(hShellDefView, IntPtr.Zero, "SysListView32", null);
    }
    return hwndDesktop;
    }
      

  3.   

    http://topic.csdn.net/t/20020525/15/751915.html
      

  4.   

    关注中, 系统 API 设置层的操作。
      

  5.   

    ——————————————————————————————————————————————————————————————————2#  非常感谢你的回复。
    但是,按照这个方法,也不能解决问题。
    窗体确实是显示在桌面上的,可是,窗体是透明的。你这边方便的话,可以试试。按照这个方法,用spy++,查询,窗体可以插入到Progman->SHELLDLL_DefView->SysListView32下,但是,窗体是透明的,虽然在桌面上,却什么都看不到。右键点击窗体,设置的右键菜单能正常显示,可是,却看不到窗体上的东西。
      

  6.   

    你简单贴一下你MainWindow的代码
      

  7.   

    用SetParent设置SysListView32是很危险的
    这样试试,用SetWindowPos把窗体设置在最顶层,然后屏蔽最小化
      

  8.   

    很奇怪啊
    楼主的要求是:始终在最前端。因为这个功能很容易实现,窗体选项中有这个。
    明显是设置了TopMost属性,楼主几位反而用SetParent设置SysListView32,那不变成最低层了?
    和楼主的要求相反了吧
      

  9.   


    topmost属性,是把窗体放在最顶端。但是,我不希望把窗体放在最顶端,只是希望不被“显示桌面”隐藏。
    因为,如果把窗体放在最顶端,太碍事了。
    我编写的是一个日历,没人把日历放在最顶端的。碍事。
      

  10.   

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;
    using System.Windows;namespace test
    {
        public partial class Form1 : Form
        {
            [DllImport("user32.dll", CharSet = CharSet.Auto)]
            public static extern IntPtr SetParent(IntPtr hChild, IntPtr hParent);
            [DllImport("User32.dll ", CharSet = CharSet.Auto)]
            public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
            [DllImport("user32.dll", CharSet = CharSet.Auto)]
            public static extern IntPtr FindWindowEx(IntPtr parent, IntPtr childe, string strclass, string strname);        private IntPtr GetDesktopPtr()//寻找桌面的句柄
            {
                // http://blog.csdn.net/mkdym/article/details/7018318
                // 情况一
                IntPtr hwndWorkerW = IntPtr.Zero;
                IntPtr hShellDefView = IntPtr.Zero;
                IntPtr hwndDesktop = IntPtr.Zero;
                IntPtr hProgMan = FindWindow("Progman", "Program Manager");
                IntPtr aa;
                if (hProgMan != IntPtr.Zero)
                {
                    hShellDefView = FindWindowEx(hProgMan, IntPtr.Zero, "SHELLDLL_DefView", null);
                    if (hShellDefView != IntPtr.Zero)
                    {
                        hwndDesktop = FindWindowEx(hShellDefView, IntPtr.Zero, "SysListView32", null);
                    }
                }
                if (hwndDesktop != IntPtr.Zero) return hwndDesktop;            // 情况二
                //必须存在桌面窗口层次
                while (hwndDesktop == IntPtr.Zero)
                {
                    //获得WorkerW类的窗口
                    hwndWorkerW = FindWindowEx(IntPtr.Zero, hwndWorkerW, "WorkerW", null);
                    if (hwndWorkerW == IntPtr.Zero) break;
                    hShellDefView = FindWindowEx(hwndWorkerW, IntPtr.Zero, "“SHELLDLL_DefView", null);
                    if (hShellDefView == IntPtr.Zero) continue;
                    hwndDesktop = FindWindowEx(hShellDefView, IntPtr.Zero, "SysListView32", null);
                }
                return hwndDesktop;
            }
            public Form1()
            {
                InitializeComponent();        }        private void Form1_Load(object sender, EventArgs e)
            {
                IntPtr desktopHwnd = GetDesktopPtr();
                //IntPtr ownHwnd = new (this).Handle;
                IntPtr result = SetParent(this.Handle, desktopHwnd);
                //this.Opacity=1;
                //MessageBox.Show(this.Handle.ToString()+"a"+desktopHwnd.ToString());
            }
      

  11.   


    我是新手,您贴的代码中的,Win32.FindWindow ,我不知道用什么命名空间,不能用,显示无法识别Win32所以,我修改了一下。非常感谢,我寻找这个方法,半个月了,始终找不到一个可行的方法。谢谢你,帮帮忙,非常感谢
      

  12.   

     [DllImport("User32.dll", EntryPoint = "SetWindowPos", SetLastError = true)]
            public static extern int SetWindowPos(IntPtr hWnd, IntPtr hWndWinInsertAfter, int x, int y, int cx, int cy, int nFlags);
     //窗口置顶,win+D失效
                const int HWND_TOPMOST = -1;
                const int SWP_NOSIZE = 0x0001;
                const int SWP_NOMOVE = 0x0002;
                SetWindowPos(Handle, (IntPtr)HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
             
      

  13.   


    非常感谢,,你的方法可以是窗体置顶。非常感谢。
    请问可不可以只屏蔽win+D,而不让窗体置顶。
    因为我编写的是一个日历,日历置顶的话,会影响电脑的正常使用,
      

  14.   


    或者,让窗体在最底层也可以,关键是屏蔽win+D。
      

  15.   

    把窗体的TopMost属性,改为true
      

  16.   

          [DllImport("user32.dll", CharSet = CharSet.Auto)]
            public static extern IntPtr FindWindow([MarshalAs(UnmanagedType.LPTStr)] string lpClassName, [MarshalAs(UnmanagedType.LPTStr)] string lpWindowName);
            [DllImport("user32")]
            private static extern IntPtr FindWindowEx(IntPtr hWnd1, IntPtr hWnd2, string lpsz1, string lpsz2);
            [DllImport("user32.dll")]
            public static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
             
            /// <summary>
            /// 钉入桌面
            /// </summary>
            public void SetParent()
            {
                IntPtr pWnd = FindWindow("Progman", null);
                pWnd = FindWindowEx(pWnd, IntPtr.Zero, "SHELLDLL_DefVIew", null);
                pWnd = FindWindowEx(pWnd, IntPtr.Zero, "SysListView32", null);
                SetParent(this.Handle, pWnd);
            }
      

  17.   

    !!!
    各位大大,我刚刚发现的。。
    在win7 系统里面,假如把win7系统的窗体视觉效果关闭,以上你们提到的方法都好用。2楼,20楼的方法,还有我在网上找到的方法,
    都可以实现显示在桌面,并且屏蔽“显示桌面”功能
    但是,如果开启Win7的显示特效。窗体会变成透明的
      

  18.   

    现在还是存在问题:开启Win7的窗体视觉效果,以上方法都不好使,窗体会变成透明的。小弟,拜托各位大大,想想办法。非常感谢。