c++ - 运行 C++ 应用程序时摆脱黑色控制台窗口

标签 c++ winapi netbeans

我正在使用 Netbeans 7.1 来研究我发现的 AI 教程 here .

编辑:我使用的是 GCC 编译器。

我已经让一切正常工作,但我似乎无法让应用程序在 Windows 子系统上编译和运行...应用程序似乎是为 Windows API 正确编写的,源代码附带的可执行文件来自该网站的文件启动时不会产生我自己的可执行文件创建的黑色控制台窗口。

我已经尝试添加 -mwindows 作为链接器的选项,并且我已经尝试了 -Wl,-subsystem,windows。这些都不适合我。我在下面提供了 main.cpp。

#define WIN32_LEAN_AND_MEAN

#include <windows.h> 

#include <stdlib.h>
#include <time.h>


#include "utils.h"
#include "CController.h"
#include "CTimer.h"
#include "resource.h"
#include "CParams.h"


// edited this out, still not working

//#pragma comment(linker, "/SUBSYSTEM:windows/ENTRY:mainCRTStartup")

///////////////////////GLOBALS ////////////////////////////////////

char*           szApplicationName = "Smart Sweepers v1.0";
char*           szWindowClassName = "sweeper";


//The controller class for this simulation
CController*    g_pController    = NULL; 

//create an instance of the parameter class.
CParams   g_Params;

//---------------------------- Cleanup ----------------------------------
//
//  simply cleans up any memory issues when the application exits
//-----------------------------------------------------------------------
void Cleanup()
{
    if (g_pController) 

        delete g_pController;
}
//-----------------------------------WinProc-----------------------------
//
//-----------------------------------------------------------------------
LRESULT CALLBACK WindowProc(HWND hwnd, 
                                        UINT msg, 
                            WPARAM wparam, 
                            LPARAM lparam)
{
    //these hold the dimensions of the client window area
    static int cxClient, cyClient;

    //used to create the back buffer
    static HDC        hdcBackBuffer;
    static HBITMAP  hBitmap;
    static HBITMAP  hOldBitmap; 


    switch(msg)
    {   
        case WM_CREATE: 
        {
            //seed the random number generator
            srand((unsigned) time(NULL));

            //get the size of the client window
            RECT rect;
            GetClientRect(hwnd, &rect);

            cxClient = rect.right;
            cyClient = rect.bottom;

            //setup the controller
            g_pController = new CController(hwnd);

                //create a surface for us to render to(backbuffer)
            hdcBackBuffer = CreateCompatibleDC(NULL);

            HDC hdc = GetDC(hwnd);

            hBitmap = CreateCompatibleBitmap(hdc,
                                                            cxClient,
                                                            cyClient);
            ReleaseDC(hwnd, hdc);

            hOldBitmap = (HBITMAP)SelectObject(hdcBackBuffer, hBitmap); 
        } 

        break;

        //check key press messages
        case WM_KEYUP:
        {
            switch(wparam)
            {

                case VK_ESCAPE:
                {
                    PostQuitMessage(0);
                }

                break;

                case 'F':
                    {
                        g_pController->FastRenderToggle();
                    }

                    break;

        //reset the demo
        case 'R':
          {
             if (g_pController)
             {
               delete g_pController;
             }

             //setup the new controller
                   g_pController = new CController(hwnd);
          }

          break;

            }//end WM_KEYUP switch
        }

        break;

        //has the user resized the client area?
        case WM_SIZE:
        {
            cxClient = LOWORD(lparam);
            cyClient = HIWORD(lparam);

            //resize the backbuffer accordingly
            SelectObject(hdcBackBuffer, hOldBitmap);

            HDC hdc = GetDC(hwnd);

            hBitmap = CreateCompatibleBitmap(hdc,
                                                             cxClient,
                                                             cyClient);
            ReleaseDC(hwnd, hdc);

            hOldBitmap = (HBITMAP)SelectObject(hdcBackBuffer, hBitmap); 
        } 

        break;

        case WM_PAINT: 
        {
      PAINTSTRUCT ps;

          BeginPaint(hwnd, &ps);

            //fill our backbuffer with white
            BitBlt(hdcBackBuffer,
             0,
             0,
             cxClient,
             cyClient,
             NULL,
             NULL,
             NULL,
             WHITENESS);

            //render the mines and sweepers
            g_pController->Render(hdcBackBuffer);

            //now blit backbuffer to front
            BitBlt(ps.hdc, 0, 0, cxClient, cyClient, hdcBackBuffer, 0, 0, SRCCOPY); 

            EndPaint(hwnd, &ps);
        } 

        break;

        case WM_DESTROY: 
        {
            SelectObject(hdcBackBuffer, hOldBitmap);

            //clean up our backbuffer objects
            DeleteDC(hdcBackBuffer);
            DeleteObject(hBitmap); 

      // kill the application, this sends a WM_QUIT message 
            PostQuitMessage(0);
        } 

        break;

        default:break;

    }//end switch

    // default msg handler 
    return (DefWindowProc(hwnd, msg, wparam, lparam));

}//end WinProc


//-----------------------------------WinMain-----------------------------------------
//  Entry point for our windows application
//-----------------------------------------------------------------------------------
int WINAPI WinMain( HINSTANCE hinstance,
                              HINSTANCE hprevinstance,
                              LPSTR lpcmdline,
                              int ncmdshow)
{

    WNDCLASSEX winclass; 
    HWND       hwnd;     
    MSG        msg;      

    // first fill in the window class stucture
    winclass.cbSize       = sizeof(WNDCLASSEX);
    winclass.style            = CS_HREDRAW | CS_VREDRAW;
    winclass.lpfnWndProc    = WindowProc;
    winclass.cbClsExtra     = 0;
    winclass.cbWndExtra     = 0;
    winclass.hInstance      = hinstance;
    winclass.hIcon            = LoadIcon(hinstance, MAKEINTRESOURCE(IDI_ICON1));
    winclass.hCursor          = LoadCursor(NULL, IDC_ARROW); 
    winclass.hbrBackground= NULL; 
    winclass.lpszMenuName   = NULL;
    winclass.lpszClassName= szWindowClassName;
    winclass.hIconSm      = LoadIcon(hinstance, MAKEINTRESOURCE(IDI_ICON1));


    // register the window class
    if (!RegisterClassEx(&winclass))
    {
        MessageBox(NULL, "Error Registering Class!", "Error", 0);
    return 0;
    }

    // create the window (one that cannot be resized)
    if (!(hwnd = CreateWindowEx(NULL,                                   
                                              szWindowClassName,                        
                                              szApplicationName,                        
                                              WS_OVERLAPPED | WS_VISIBLE | WS_CAPTION | WS_SYSMENU,
                              GetSystemMetrics(SM_CXSCREEN)/2 - CParams::WindowWidth/2,
                              GetSystemMetrics(SM_CYSCREEN)/2 - CParams::WindowHeight/2,                                    
                                              CParams::WindowWidth,
                              CParams::WindowHeight,                
                                              NULL,                                 
                                              NULL,                             
                                              hinstance,                                
                                              NULL)))   
    {
    MessageBox(NULL, "Error Creating Window!", "Error", 0);
        return 0;
    }

    //Show the window
    ShowWindow(hwnd, SW_SHOWDEFAULT );
    UpdateWindow(hwnd);

    //create a timer
    CTimer timer(CParams::iFramesPerSecond);

    //start the timer
    timer.Start();

    // Enter the message loop
    bool bDone = FALSE;

    while(!bDone)
    {

        while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ) 
        {
            if( msg.message == WM_QUIT ) 
            {
                //Stop loop if it's a quit message
                bDone = TRUE;
            } 

            else 
            {
                TranslateMessage( &msg );
                DispatchMessage( &msg );
            }
        }

        if (timer.ReadyForNextFrame() || g_pController->FastRender())
        {   
          if(!g_pController->Update())
            {
                //we have a problem, end app
                bDone = TRUE;
            }

            //this will call WM_PAINT which will render our scene
            InvalidateRect(hwnd, NULL, TRUE);
            UpdateWindow(hwnd);
    }                   

    }//end while


    // Clean up everything and exit the app
    Cleanup();
    UnregisterClass( szWindowClassName, winclass.hInstance );

    return 0;

} // end WinMain

最佳答案

这看起来有点奇怪,但是 windows 子系统应用程序使用 WinMainCRTStartup 作为入口点。所以下面这行看起来不一致:

#pragma comment(linker, "/SUBSYSTEM:windows /ENTRY:mainCRTStartup")

它可能应该是 "/SUBSYSTEM:windows/ENTRY:WinMainCRTStartup""/SUBSYSTEM:console/ENTRY:mainCRTStartup"

另一方面,我从未尝试过使用 gcc 制作 Windows 应用程序。它可能会完全忽略这个#pragma...无论如何,尝试将其注释掉,看看会发生什么。通常编译器应该能够在没有编译时参数的情况下选择正确的入口点。

关于c++ - 运行 C++ 应用程序时摆脱黑色控制台窗口,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8774883/

相关文章:

winapi - 驱动器上剩余的可用空间 - WinAPI - Windows CE

java - 我想在基于Java的Net beans中创建一个桌面应用程序

java - Netbeans java 项目中出现不稳定行为

C++ 服务示例 - Unicode 转换

c++ - 运算符在模板化动态数组中重载 []

c++ - 是否有 SHGetSpecialFolderLocation 的新替代品?

c++ - Winapi - WM_CLOSE 的替代品

java - 如何在 Java NetBeans 中显示 CJK 字符和 GUI?

c++ - 错误 LNK2001 : unresolved external symbol "public: double __thiscall

c++ - 以二进制模式扫描文件并将十六进制字符解释为 C++ 中的实际数字