来自控制台项目的WPF窗口?

时间:2021-11-29 06:48:44

I recently started a C# project (VS 2008) as a 'Console' project where I wrote a few libraries, test programs, etc. Now I'd like to add a couple of WPF windows, but it looks like console project won't let me do that. I'm coming from Java so this is a little strange. How can I add a WPF form (which I will instantiate my self from my "main" class?

我最近启动了一个c#项目(VS 2008),作为一个“控制台”项目,在这里我编写了一些库、测试程序等等。我来自Java,这有点奇怪。如何添加WPF表单(我将从“main”类中实例化我自己?

5 个解决方案

#1


0  

Are you sure you need Console project? You can create 'WPF application' project and add references to your libraries, etc. If try to show WPF window from console app you will gen an exception due to differences in threading model between Console & WPF apps.

你确定你需要控制台项目吗?您可以创建“WPF应用程序”项目并向您的库添加引用,等等。如果试图从控制台应用程序显示WPF窗口,由于控制台和WPF应用程序之间的线程模型不同,您将产生一个异常。

#2


38  

The accepted answer is not entirely true, I'm afraid, just add the [STAThread] attribute before your mainmethod and make references to the right libraries (like System.Windows) and you're all set to add wpf windows.

我担心,被接受的答案并不完全正确,只需要在主方法之前添加[STAThread]属性,并对正确的库(如System.Windows)进行引用,然后您就可以添加wpf窗口了。

EDIT : in the comments @JamesWilkins supplied me with this usefull link : http://code-phix.blogspot.be/2013/11/creating-wpf-project-from-scratch.html

编辑:在注释@JamesWilkins给我提供了这个有用的链接:http://code-phix.blogspot.be/2013/11/creating-wpf-project-from-scratch.html

#3


17  

I had the same question and was looking for a similar answer. I found info all over the place, so I'm putting what I found in one place. I also needed a way to hide and show the console window, so I found out this worked (for VS 2013+):

我也有同样的问题,正在寻找相似的答案。我到处都能找到信息,所以我把我找到的东西放在一个地方。我还需要一种隐藏和显示控制台窗口的方法,所以我发现这个方法是有效的(VS 2013+):

  1. Create a new console project (be sure to select the .NET framework version you need to use - I needed to use .Net 4.0 myself). Make sure to have the following references:

    创建一个新的控制台项目(一定要选择你需要使用的。net框架版本——我自己也需要使用。net 4.0)。确保有以下参考资料:

    • PresentationFramework
    • PresentationFramework
    • PresentationCore
    • PresentationCore
    • WindowsBase
    • WindowsBase
    • System.xaml
    • System.xaml
  2. Right-click on the project in the solution explorer, select "Properties", and change the project Output Type to Windows Application. This prevents the console window from showing on startup (if you want that, skip this step).

    右键单击解决方案资源管理器中的项目,选择“Properties”,并将项目输出类型更改为Windows应用程序。这将防止控制台窗口在启动时显示(如果您想要的话,跳过这一步)。

  3. While controlling the console window is not necessary in order to add WPF windows, it can be useful. If you don't need this, skip to #4. In the "Program" class for the console, add this in order to control the window:

    虽然控制控制台窗口并不是添加WPF窗口所必需的,但是它是有用的。如果您不需要这个,请跳到第4条。在控制台的“Program”类中,添加这个以控制窗口:

    public class Program
    {
      [DllImport("kernel32.dll", SetLastError = true)]
      static extern bool AllocConsole(); // Create console window
    
      [DllImport("kernel32.dll")]
      static extern IntPtr GetConsoleWindow(); // Get console window handle
    
      [DllImport("user32.dll")]
      static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
    
      const int SW_HIDE = 0;
      const int SW_SHOW = 5;
    

    This allows to create, hide, and show the console window. I created these methods to do this:

    这允许创建、隐藏和显示控制台窗口。我创造了这些方法来做到这一点:

      static void ShowConsole()
      {
          var handle = GetConsoleWindow();
          if (handle == IntPtr.Zero)
              AllocConsole();
          else
              ShowWindow(handle, SW_SHOW);
      }
    
      static void HideConsole()
      {
          var handle = GetConsoleWindow();
          if (handle != null)
              ShowWindow(handle, SW_HIDE);
      }
    

    These are mostly self explanatory, but if the project is in window mode, GetConsoleWindow(); returns null, so here we test if the handle is null (zero in this case), and if so, a console window needs to be created (only once). After this, GetConsoleWindow(); will always return a handle to use.

    这些大部分是自解释的,但是如果项目处于窗口模式,GetConsoleWindow();返回null,因此我们在这里测试句柄是否为null(在本例中为0),如果是,则需要创建一个控制台窗口(只有一次)。在这之后,GetConsoleWindow();将始终返回一个要使用的句柄。

  4. As stated in another answer already, you need to add [STAThread] on a line before your console's Main method. This is required, as WPF needs to run in a Single Threaded Apartment environment.

    正如已经在另一个答案中所述,您需要在控制台的主方法之前在一行中添加[STAThread]。这是必需的,因为WPF需要在单线程的公寓环境中运行。

      [STAThread]
      static void Main(string[] args)
      {
      }
    
  5. Adding a window: To do this, just add a user control to your project and name it "MainWindow" (or whatever you like). Just right-click the project node in the solution explorer and select Add->User Control.... Open the MainWindow.xaml.cs code behind and change MainWindow : UserControl to MainWindow : Window. Next, open the MainWindow.xaml file and change the first tag <UserControl to <Window (and make sure the closing tag gets renamed also, which should be automatic if using Visual Studio). Close all "MainWindow" editor tabs and reopen (just to be sure, may not be necessary). You should see MainWindow.xaml now show a window in the design pane.

    添加一个窗口:要做到这一点,只需向您的项目添加一个用户控件,并将其命名为“MainWindow”(或者您喜欢的任何东西)。只是在解决方案资源管理器中右键单击项目节点并选择Add - >用户控件....打开MainWindow.xaml。cs代码后变主窗口:UserControl到MainWindow:窗口。接下来,打开主窗口。xaml文件并将第一个标签 更改为

  6. Showing the WPF window: To do this, we need to start the window message loop, which is really easy. To begin, I created some properties to store the objects. Just put this somewhere in the Program class.

    显示WPF窗口:要做到这一点,我们需要启动窗口消息循环,这非常简单。首先,我创建了一些属性来存储对象。把这个放到程序类的某个地方。

    public static Application WinApp { get; private set; }
    public static Window MainWindow { get; private set; }
    

    Next we have to create the message loop by creating a System.Windows.Application object, then pass it the main window. I created this method to perform this task:

    接下来,我们必须通过创建System.Windows创建消息循环。应用程序对象,然后将其传递到主窗口。我创建这个方法来执行这个任务:

    static void InitializeWindows()
    {
        WinApp = new Application();
        WinApp.Run(MainWindow = new MainWindow()); // note: blocking call
    }
    

    and that's it! To test this, put some content in your main window and do this:

    这是它!要测试这一点,请在主窗口中放置一些内容,然后这样做:

    [STAThread]
    static void Main(string[] args)
    {
        ShowConsole(); // Show the console window (for Win App projects)
        Console.WriteLine("Opening window...");
        InitializeWindows(); // opens the WPF window and waits here
        Console.WriteLine("Exiting main...");
    }
    

Hope that helps saves someone time, cheers! ;)

希望这能帮助别人节省时间,干杯!,)

TIP: I found it helpful, in my case, to call InitializeWindows() in a new thread; however, that means that you must create UI objects (among other things) in the the same thread that the Application object was created in. To communicate with the new thread, I just used the Dispatcher class (WinApp.Dispatcher.BeginInvoke()) to run requests in the WPF thread context.

提示:我发现在新线程中调用InitializeWindows()非常有用;但是,这意味着您必须在创建应用程序对象的同一个线程中创建UI对象(以及其他东西)。为了与新的线程进行通信,我仅使用Dispatcher类(WinApp.Dispatcher.BeginInvoke()))在WPF线程上下文中运行请求。

For Windows 8/10: If you are debugging and you don't see any text in your output window, take a look here: https://*.com/a/49145317/1236397

对于Windows 8/10:如果您正在调试,并且在输出窗口中没有看到任何文本,请查看这里:https://*.com/a/49145317/1236397

#4


3  

You should move your library code to some other "Class library" project and use it from your Console project. Your WPF windows should be in another "WPF application" project which will also reference your "Class library".

您应该将库代码移动到其他“类库”项目中,并从控制台项目中使用它。您的WPF窗口应该位于另一个“WPF应用程序”项目中,该项目也将引用您的“类库”。

#5


0  

Thanks to aku and Dmitriy, I create another project (WPF) which will reference my console based code.

感谢aku和Dmitriy,我创建了另一个项目(WPF),它将引用基于控制台的代码。

#1


0  

Are you sure you need Console project? You can create 'WPF application' project and add references to your libraries, etc. If try to show WPF window from console app you will gen an exception due to differences in threading model between Console & WPF apps.

你确定你需要控制台项目吗?您可以创建“WPF应用程序”项目并向您的库添加引用,等等。如果试图从控制台应用程序显示WPF窗口,由于控制台和WPF应用程序之间的线程模型不同,您将产生一个异常。

#2


38  

The accepted answer is not entirely true, I'm afraid, just add the [STAThread] attribute before your mainmethod and make references to the right libraries (like System.Windows) and you're all set to add wpf windows.

我担心,被接受的答案并不完全正确,只需要在主方法之前添加[STAThread]属性,并对正确的库(如System.Windows)进行引用,然后您就可以添加wpf窗口了。

EDIT : in the comments @JamesWilkins supplied me with this usefull link : http://code-phix.blogspot.be/2013/11/creating-wpf-project-from-scratch.html

编辑:在注释@JamesWilkins给我提供了这个有用的链接:http://code-phix.blogspot.be/2013/11/creating-wpf-project-from-scratch.html

#3


17  

I had the same question and was looking for a similar answer. I found info all over the place, so I'm putting what I found in one place. I also needed a way to hide and show the console window, so I found out this worked (for VS 2013+):

我也有同样的问题,正在寻找相似的答案。我到处都能找到信息,所以我把我找到的东西放在一个地方。我还需要一种隐藏和显示控制台窗口的方法,所以我发现这个方法是有效的(VS 2013+):

  1. Create a new console project (be sure to select the .NET framework version you need to use - I needed to use .Net 4.0 myself). Make sure to have the following references:

    创建一个新的控制台项目(一定要选择你需要使用的。net框架版本——我自己也需要使用。net 4.0)。确保有以下参考资料:

    • PresentationFramework
    • PresentationFramework
    • PresentationCore
    • PresentationCore
    • WindowsBase
    • WindowsBase
    • System.xaml
    • System.xaml
  2. Right-click on the project in the solution explorer, select "Properties", and change the project Output Type to Windows Application. This prevents the console window from showing on startup (if you want that, skip this step).

    右键单击解决方案资源管理器中的项目,选择“Properties”,并将项目输出类型更改为Windows应用程序。这将防止控制台窗口在启动时显示(如果您想要的话,跳过这一步)。

  3. While controlling the console window is not necessary in order to add WPF windows, it can be useful. If you don't need this, skip to #4. In the "Program" class for the console, add this in order to control the window:

    虽然控制控制台窗口并不是添加WPF窗口所必需的,但是它是有用的。如果您不需要这个,请跳到第4条。在控制台的“Program”类中,添加这个以控制窗口:

    public class Program
    {
      [DllImport("kernel32.dll", SetLastError = true)]
      static extern bool AllocConsole(); // Create console window
    
      [DllImport("kernel32.dll")]
      static extern IntPtr GetConsoleWindow(); // Get console window handle
    
      [DllImport("user32.dll")]
      static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
    
      const int SW_HIDE = 0;
      const int SW_SHOW = 5;
    

    This allows to create, hide, and show the console window. I created these methods to do this:

    这允许创建、隐藏和显示控制台窗口。我创造了这些方法来做到这一点:

      static void ShowConsole()
      {
          var handle = GetConsoleWindow();
          if (handle == IntPtr.Zero)
              AllocConsole();
          else
              ShowWindow(handle, SW_SHOW);
      }
    
      static void HideConsole()
      {
          var handle = GetConsoleWindow();
          if (handle != null)
              ShowWindow(handle, SW_HIDE);
      }
    

    These are mostly self explanatory, but if the project is in window mode, GetConsoleWindow(); returns null, so here we test if the handle is null (zero in this case), and if so, a console window needs to be created (only once). After this, GetConsoleWindow(); will always return a handle to use.

    这些大部分是自解释的,但是如果项目处于窗口模式,GetConsoleWindow();返回null,因此我们在这里测试句柄是否为null(在本例中为0),如果是,则需要创建一个控制台窗口(只有一次)。在这之后,GetConsoleWindow();将始终返回一个要使用的句柄。

  4. As stated in another answer already, you need to add [STAThread] on a line before your console's Main method. This is required, as WPF needs to run in a Single Threaded Apartment environment.

    正如已经在另一个答案中所述,您需要在控制台的主方法之前在一行中添加[STAThread]。这是必需的,因为WPF需要在单线程的公寓环境中运行。

      [STAThread]
      static void Main(string[] args)
      {
      }
    
  5. Adding a window: To do this, just add a user control to your project and name it "MainWindow" (or whatever you like). Just right-click the project node in the solution explorer and select Add->User Control.... Open the MainWindow.xaml.cs code behind and change MainWindow : UserControl to MainWindow : Window. Next, open the MainWindow.xaml file and change the first tag <UserControl to <Window (and make sure the closing tag gets renamed also, which should be automatic if using Visual Studio). Close all "MainWindow" editor tabs and reopen (just to be sure, may not be necessary). You should see MainWindow.xaml now show a window in the design pane.

    添加一个窗口:要做到这一点,只需向您的项目添加一个用户控件,并将其命名为“MainWindow”(或者您喜欢的任何东西)。只是在解决方案资源管理器中右键单击项目节点并选择Add - >用户控件....打开MainWindow.xaml。cs代码后变主窗口:UserControl到MainWindow:窗口。接下来,打开主窗口。xaml文件并将第一个标签 更改为

  6. Showing the WPF window: To do this, we need to start the window message loop, which is really easy. To begin, I created some properties to store the objects. Just put this somewhere in the Program class.

    显示WPF窗口:要做到这一点,我们需要启动窗口消息循环,这非常简单。首先,我创建了一些属性来存储对象。把这个放到程序类的某个地方。

    public static Application WinApp { get; private set; }
    public static Window MainWindow { get; private set; }
    

    Next we have to create the message loop by creating a System.Windows.Application object, then pass it the main window. I created this method to perform this task:

    接下来,我们必须通过创建System.Windows创建消息循环。应用程序对象,然后将其传递到主窗口。我创建这个方法来执行这个任务:

    static void InitializeWindows()
    {
        WinApp = new Application();
        WinApp.Run(MainWindow = new MainWindow()); // note: blocking call
    }
    

    and that's it! To test this, put some content in your main window and do this:

    这是它!要测试这一点,请在主窗口中放置一些内容,然后这样做:

    [STAThread]
    static void Main(string[] args)
    {
        ShowConsole(); // Show the console window (for Win App projects)
        Console.WriteLine("Opening window...");
        InitializeWindows(); // opens the WPF window and waits here
        Console.WriteLine("Exiting main...");
    }
    

Hope that helps saves someone time, cheers! ;)

希望这能帮助别人节省时间,干杯!,)

TIP: I found it helpful, in my case, to call InitializeWindows() in a new thread; however, that means that you must create UI objects (among other things) in the the same thread that the Application object was created in. To communicate with the new thread, I just used the Dispatcher class (WinApp.Dispatcher.BeginInvoke()) to run requests in the WPF thread context.

提示:我发现在新线程中调用InitializeWindows()非常有用;但是,这意味着您必须在创建应用程序对象的同一个线程中创建UI对象(以及其他东西)。为了与新的线程进行通信,我仅使用Dispatcher类(WinApp.Dispatcher.BeginInvoke()))在WPF线程上下文中运行请求。

For Windows 8/10: If you are debugging and you don't see any text in your output window, take a look here: https://*.com/a/49145317/1236397

对于Windows 8/10:如果您正在调试,并且在输出窗口中没有看到任何文本,请查看这里:https://*.com/a/49145317/1236397

#4


3  

You should move your library code to some other "Class library" project and use it from your Console project. Your WPF windows should be in another "WPF application" project which will also reference your "Class library".

您应该将库代码移动到其他“类库”项目中,并从控制台项目中使用它。您的WPF窗口应该位于另一个“WPF应用程序”项目中,该项目也将引用您的“类库”。

#5


0  

Thanks to aku and Dmitriy, I create another project (WPF) which will reference my console based code.

感谢aku和Dmitriy,我创建了另一个项目(WPF),它将引用基于控制台的代码。