Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
CODE PROJECT For Those Who Code
  • Home
  • Articles
  • FAQ
Community
  1. Home
  2. General Programming
  3. C#
  4. Creating hidden window [modified]

Creating hidden window [modified]

Scheduled Pinned Locked Moved C#
csharpcomdesignlinuxhelp
9 Posts 3 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • M Offline
    M Offline
    mikker_123
    wrote on last edited by
    #1

    I've made custom shell for purposes of one application. However I have problems with slow printing. I've found solution on: link to post but still can't make C# equivalent of code on that location. Can someone help me on making this hidden "PrintTray_Notify_WndClass" window? Thanks in advance.

    L 1 Reply Last reply
    0
    • M mikker_123

      I've made custom shell for purposes of one application. However I have problems with slow printing. I've found solution on: link to post but still can't make C# equivalent of code on that location. Can someone help me on making this hidden "PrintTray_Notify_WndClass" window? Thanks in advance.

      L Offline
      L Offline
      Luc Pattyn
      wrote on last edited by
      #2

      I have created the following, based on PInvoke and unmanaged code in Windows dlls. It always gives the error "ALREADY_EXISTS", probably since I am run Windows Explorer...

      private void mniCodeProject_Click(object sender, System.EventArgs e) {
      int handle=CreateWindowEx(
      0, // extended style
      "PrintTray_Notify_WndClass", // class name
      "", // window name
      0x80000000, // style=WS_POPUP
      0,0,10,10, // bounds
      IntPtr.Zero, // no parent
      IntPtr.Zero, // no menu
      IntPtr.Zero, // instance (gets ignored)
      IntPtr.Zero); // no lpParam
      log("handle="+handle.ToString("X8"));
      if (handle==0) {
      int i=GetLastError();
      string s="";
      if (i==183) s=" ERROR_ALREADY_EXISTS";
      log("last error="+i.ToString("X8")+s);
      }
      }

      [DllImport("kernel32.dll", CallingConvention=CallingConvention.StdCall)]
      private static extern int GetLastError();

      [DllImport("user32.dll", EntryPoint="CreateWindowEx", CallingConvention=CallingConvention.StdCall)]
      public static extern int CreateWindowEx(uint style2, string className,
      string windowName, uint style, int x, int y, int w, int h, IntPtr parent,
      IntPtr menu, IntPtr instance, IntPtr lpParam);

      You will have to add some #using statements, and to replace my log function by yours (could be Console.WriteLine). I am not sure how long the Window will live, and/or whether you should delete it when it is no longer needed... Good luck with it. :)

      Luc Pattyn

      M M 2 Replies Last reply
      0
      • L Luc Pattyn

        I have created the following, based on PInvoke and unmanaged code in Windows dlls. It always gives the error "ALREADY_EXISTS", probably since I am run Windows Explorer...

        private void mniCodeProject_Click(object sender, System.EventArgs e) {
        int handle=CreateWindowEx(
        0, // extended style
        "PrintTray_Notify_WndClass", // class name
        "", // window name
        0x80000000, // style=WS_POPUP
        0,0,10,10, // bounds
        IntPtr.Zero, // no parent
        IntPtr.Zero, // no menu
        IntPtr.Zero, // instance (gets ignored)
        IntPtr.Zero); // no lpParam
        log("handle="+handle.ToString("X8"));
        if (handle==0) {
        int i=GetLastError();
        string s="";
        if (i==183) s=" ERROR_ALREADY_EXISTS";
        log("last error="+i.ToString("X8")+s);
        }
        }

        [DllImport("kernel32.dll", CallingConvention=CallingConvention.StdCall)]
        private static extern int GetLastError();

        [DllImport("user32.dll", EntryPoint="CreateWindowEx", CallingConvention=CallingConvention.StdCall)]
        public static extern int CreateWindowEx(uint style2, string className,
        string windowName, uint style, int x, int y, int w, int h, IntPtr parent,
        IntPtr menu, IntPtr instance, IntPtr lpParam);

        You will have to add some #using statements, and to replace my log function by yours (could be Console.WriteLine). I am not sure how long the Window will live, and/or whether you should delete it when it is no longer needed... Good luck with it. :)

        Luc Pattyn

        M Offline
        M Offline
        mikker_123
        wrote on last edited by
        #3

        First of all thanks for your code. Now, I'm having trouble using it, as I always get error code: 1400 ("Invalid window handle") exception. I tried on three computers and it's happens on all of them. Any idea how I can solve this problem? Thanks in advance!

        L 1 Reply Last reply
        0
        • M mikker_123

          First of all thanks for your code. Now, I'm having trouble using it, as I always get error code: 1400 ("Invalid window handle") exception. I tried on three computers and it's happens on all of them. Any idea how I can solve this problem? Thanks in advance!

          L Offline
          L Offline
          Luc Pattyn
          wrote on last edited by
          #4

          I need more info to form an opinion on this. Is 1400 hex or decimal ? is it exactly my code that reports "handle=00000000" and "last error=00001400" ?? Please provide exact code and output. What is your OS (winXP ? any service pack ?) and .NET version (1.1, 2.0 ? any service pack?) Furthermore, I have some ideas. Idea 1: I am not sure, maybe it is necessary to prefix my code by the following:

          SetLastError(0);
          

          together with the declaration:

          [DllImport("kernel32.dll", CallingConvention=CallingConvention.StdCall)]
          private static extern int SetLastError(int err);

          Rationale: a lot of system calls change the "last error" value only when something goes wrong, but don't clear it beforehand. This is what SetLastError(0) is about. (So it may have been set by CreateWindow or any call executed earlier). Idea 2: there might be a problem with the className/windowName arguments (ASCII/Unicode confusion). If so, this could be fixed by specifying CharSet=CharSet.ASCII or Unicode inside the DllImport line of CreateWindowEx declaration, and/or by changing the EntryPoint to either CreateWindowExA or CreateWindowExW. :)

          Luc Pattyn

          M 1 Reply Last reply
          0
          • L Luc Pattyn

            I need more info to form an opinion on this. Is 1400 hex or decimal ? is it exactly my code that reports "handle=00000000" and "last error=00001400" ?? Please provide exact code and output. What is your OS (winXP ? any service pack ?) and .NET version (1.1, 2.0 ? any service pack?) Furthermore, I have some ideas. Idea 1: I am not sure, maybe it is necessary to prefix my code by the following:

            SetLastError(0);
            

            together with the declaration:

            [DllImport("kernel32.dll", CallingConvention=CallingConvention.StdCall)]
            private static extern int SetLastError(int err);

            Rationale: a lot of system calls change the "last error" value only when something goes wrong, but don't clear it beforehand. This is what SetLastError(0) is about. (So it may have been set by CreateWindow or any call executed earlier). Idea 2: there might be a problem with the className/windowName arguments (ASCII/Unicode confusion). If so, this could be fixed by specifying CharSet=CharSet.ASCII or Unicode inside the DllImport line of CreateWindowEx declaration, and/or by changing the EntryPoint to either CreateWindowExA or CreateWindowExW. :)

            Luc Pattyn

            M Offline
            M Offline
            mikker_123
            wrote on last edited by
            #5

            Here is more info: -1400 is decimal, it gives 00000578 when I put i.ToString("X8"). -my OS i WinXP and .NET is 2.0 Here is complete code: public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { SetLastError(0); int handle = CreateWindowEx( 0, // extended style "PrintTray_Notify_WndClass", // class name "", // window name 0x80000000, // style=WS_POPUP 0, 0, 10, 10, // bounds IntPtr.Zero, // no parent IntPtr.Zero, // no menu IntPtr.Zero, // instance (gets ignored) IntPtr.Zero); // no lpParam MessageBox.Show("Handle: "+ handle.ToString("X8")); if (handle == 0) { int i = GetLastError(); if (i == 183) MessageBox.Show("ERROR_ALREADY_EXISTS"); else MessageBox.Show("error code:"+ i.ToString("X8")); } } [DllImport("kernel32.dll", CallingConvention = CallingConvention.StdCall)] private static extern int GetLastError(); [DllImport("kernel32.dll", CallingConvention = CallingConvention.StdCall)] private static extern int SetLastError(int err); [DllImport("user32.dll", CharSet = CharSet.Auto, EntryPoint = "CreateWindowEx", CallingConvention = CallingConvention.StdCall)] public static extern int CreateWindowEx(uint style2, string className, string windowName, uint style, int x, int y, int w, int h, IntPtr parent, IntPtr menu, IntPtr instance, IntPtr lpParam); } And it always gets to: MessageBox.Show("error code:"+ i.ToString("X8")); giving 00000573. I tried your two ideas and nothing happens. Can you give me any more help? Thanks!

            L 1 Reply Last reply
            0
            • M mikker_123

              Here is more info: -1400 is decimal, it gives 00000578 when I put i.ToString("X8"). -my OS i WinXP and .NET is 2.0 Here is complete code: public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { SetLastError(0); int handle = CreateWindowEx( 0, // extended style "PrintTray_Notify_WndClass", // class name "", // window name 0x80000000, // style=WS_POPUP 0, 0, 10, 10, // bounds IntPtr.Zero, // no parent IntPtr.Zero, // no menu IntPtr.Zero, // instance (gets ignored) IntPtr.Zero); // no lpParam MessageBox.Show("Handle: "+ handle.ToString("X8")); if (handle == 0) { int i = GetLastError(); if (i == 183) MessageBox.Show("ERROR_ALREADY_EXISTS"); else MessageBox.Show("error code:"+ i.ToString("X8")); } } [DllImport("kernel32.dll", CallingConvention = CallingConvention.StdCall)] private static extern int GetLastError(); [DllImport("kernel32.dll", CallingConvention = CallingConvention.StdCall)] private static extern int SetLastError(int err); [DllImport("user32.dll", CharSet = CharSet.Auto, EntryPoint = "CreateWindowEx", CallingConvention = CallingConvention.StdCall)] public static extern int CreateWindowEx(uint style2, string className, string windowName, uint style, int x, int y, int w, int h, IntPtr parent, IntPtr menu, IntPtr instance, IntPtr lpParam); } And it always gets to: MessageBox.Show("error code:"+ i.ToString("X8")); giving 00000573. I tried your two ideas and nothing happens. Can you give me any more help? Thanks!

              L Offline
              L Offline
              Luc Pattyn
              wrote on last edited by
              #6

              One or more of the arguments to CreateWindowEx seems to be wrong. If we assume Windows did report an accurate error code (ERROR_INVALID_WINDOW_HANDLE), then the problem must be with one of the handles (i.e. parent/menu/instance/lpParam) but then MSDN says: - parent: "This parameter is optional for pop-up windows" - menu: more complex text, but then there also exists ERROR_INVALID_MENU_HANDLE which is not what you are getting - instance: "Windows NT/2000/XP: This value is ignored" but your reference article did supply hInstance here (I replaced it by null because of MSDN's "is ignored") - lpParam: is explained as a pointer, not really a handler. So maybe MSDN is wrong and it just needs an hInstance. Getting hInstance is somewhat tricky; my best guess is:

              IntPtr hInstance=Marshal.GetHINSTANCE(GetType().Module);

              which only works inside an instance (= non-static) method. Once again good luck ! BTW, you are not running on a 64-bit OS by any chance ? :)

              Luc Pattyn

              M 1 Reply Last reply
              0
              • L Luc Pattyn

                One or more of the arguments to CreateWindowEx seems to be wrong. If we assume Windows did report an accurate error code (ERROR_INVALID_WINDOW_HANDLE), then the problem must be with one of the handles (i.e. parent/menu/instance/lpParam) but then MSDN says: - parent: "This parameter is optional for pop-up windows" - menu: more complex text, but then there also exists ERROR_INVALID_MENU_HANDLE which is not what you are getting - instance: "Windows NT/2000/XP: This value is ignored" but your reference article did supply hInstance here (I replaced it by null because of MSDN's "is ignored") - lpParam: is explained as a pointer, not really a handler. So maybe MSDN is wrong and it just needs an hInstance. Getting hInstance is somewhat tricky; my best guess is:

                IntPtr hInstance=Marshal.GetHINSTANCE(GetType().Module);

                which only works inside an instance (= non-static) method. Once again good luck ! BTW, you are not running on a 64-bit OS by any chance ? :)

                Luc Pattyn

                M Offline
                M Offline
                mikker_123
                wrote on last edited by
                #7

                Funny thing about this is that when using NativeWindow (.NET wrapper class over CreateWindowEx), I get same error... NativeWindow nw = new NativeWindow(); CreateParams cp = new CreateParams(); cp.ExStyle = 0; cp.ClassName = "PrintTray_Notify_WndClass"; cp.Caption = ""; nw.CreateHandle(cp); I wish I'm using 64-bit OS... I'm getting desperate this way - can't create one window for two days :).

                L 1 Reply Last reply
                0
                • M mikker_123

                  Funny thing about this is that when using NativeWindow (.NET wrapper class over CreateWindowEx), I get same error... NativeWindow nw = new NativeWindow(); CreateParams cp = new CreateParams(); cp.ExStyle = 0; cp.ClassName = "PrintTray_Notify_WndClass"; cp.Caption = ""; nw.CreateHandle(cp); I wish I'm using 64-bit OS... I'm getting desperate this way - can't create one window for two days :).

                  L Offline
                  L Offline
                  Luc Pattyn
                  wrote on last edited by
                  #8

                  Hi Mikker, I wasnt aware of NativeWindow and CreateParams classes. These make my code unnecessary (but it seems to confirm it was correct...) So there must be a deeper problem somewhere. Did you Google it ? Or try Microsoft Connect ? BTW, dit you try the same on .NET 1.1 ? :)

                  Luc Pattyn

                  1 Reply Last reply
                  0
                  • L Luc Pattyn

                    I have created the following, based on PInvoke and unmanaged code in Windows dlls. It always gives the error "ALREADY_EXISTS", probably since I am run Windows Explorer...

                    private void mniCodeProject_Click(object sender, System.EventArgs e) {
                    int handle=CreateWindowEx(
                    0, // extended style
                    "PrintTray_Notify_WndClass", // class name
                    "", // window name
                    0x80000000, // style=WS_POPUP
                    0,0,10,10, // bounds
                    IntPtr.Zero, // no parent
                    IntPtr.Zero, // no menu
                    IntPtr.Zero, // instance (gets ignored)
                    IntPtr.Zero); // no lpParam
                    log("handle="+handle.ToString("X8"));
                    if (handle==0) {
                    int i=GetLastError();
                    string s="";
                    if (i==183) s=" ERROR_ALREADY_EXISTS";
                    log("last error="+i.ToString("X8")+s);
                    }
                    }

                    [DllImport("kernel32.dll", CallingConvention=CallingConvention.StdCall)]
                    private static extern int GetLastError();

                    [DllImport("user32.dll", EntryPoint="CreateWindowEx", CallingConvention=CallingConvention.StdCall)]
                    public static extern int CreateWindowEx(uint style2, string className,
                    string windowName, uint style, int x, int y, int w, int h, IntPtr parent,
                    IntPtr menu, IntPtr instance, IntPtr lpParam);

                    You will have to add some #using statements, and to replace my log function by yours (could be Console.WriteLine). I am not sure how long the Window will live, and/or whether you should delete it when it is no longer needed... Good luck with it. :)

                    Luc Pattyn

                    M Offline
                    M Offline
                    mmf
                    wrote on last edited by
                    #9

                    Dear Luc. I found your answer on problem at slow printing when custom shell is used. I tried to use PrintTray_notify_WndClass class to create window, but I get error 1407=cannot find wnd class. What is wrong? Tnx, Matjaž

                    1 Reply Last reply
                    0
                    Reply
                    • Reply as topic
                    Log in to reply
                    • Oldest to Newest
                    • Newest to Oldest
                    • Most Votes


                    • Login

                    • Don't have an account? Register

                    • Login or register to search.
                    • First post
                      Last post
                    0
                    • Categories
                    • Recent
                    • Tags
                    • Popular
                    • World
                    • Users
                    • Groups