编辑框SetWindowText打破了框

时间:2014-03-15 04:18:54

标签: c++ winapi

(对不起长度)    我遇到的问题是具体使用文本框控件上的SetWindowText函数。我设置了它,所以当我按下“拍摄”按钮时,它会抓取文本框中的内容,检查其输入,如果有效则将其抛出一些变量以供游戏运行。一切正常,除非我在其中一个文本框上使用SetWindowText(我试图让文本框在你单击时清除它的文本)它会清除文本,但之后我会对它做任何输入崩溃程序以及如果我退出程序退出时出错。错误通常如下:

"Unhandled exception at 0x77CE220F (ntdll.dll) in Physics Project 0.3 Cleaned Up.exe:     0xC0000005: Access violation writing location 0x00060FB4."

虽然有时会说“ntdll.dll”,但它会说“kernel.dll”或“user32.dll”    它跳转到的常见断点是在字符串头文件中,它在读取时断开的代码

const value_type *_Myptr() const
        {   // determine current pointer to buffer for nonmutable string
        return (this->_BUF_SIZE <= this->_Myres
            ? _STD addressof(*this->_Bx._Ptr)
            : this->_Bx._Buf);
        }

我尝试使用字符串和char数组来尝试避免使用不可变字符串以及只是将TEXT(“”)直接插入到SetWindowText调用中但没有任何工作

我正在做这个项目作为我的C ++课程的荣誉项目,所以我从Win32和DirectX自学了这个项目的所有内容,所以如果有一个非常明显的错误,我道歉。除了错误,我想知道清理退出时为窗口分配的内存。我在WinMain的末尾有一组ZeroMemory调用我创建的所有窗口,因为在没有清理内存的情况下结束程序感觉很奇怪但是我真的没有看到其他人有那些让我知道如果那是不需要的或者如果有不同的方式。

代码我遇到问题:

using namespace std;

///////////////////// Window/Control Handles ////////////////////
HWND hButton;               // Shoot button
HWND hTextBoxVeloc;         // Velocity Entry Field
HWND hTextBoxAngle;         // Angle Entry Field

enum ControlList { ID_BUTTON, ID_VELOC_TB, ID_ANGLE_TB };

////////////////////// User Input Variables /////////////////////
int   getTextWinState;
char  velocEntered[ENTRY_SIZE];
float userVeloc;
char  angleEntered[ENTRY_SIZE];
float userAngle;
bool  hButtonClicked = false;

short  troopDist;
string troopDistStr;
const short TEN = 10;

//***************************************************************
//string blankBox = "";
//char blankBox[1];
//***************************************************************


/////////////////////////// Prototypes //////////////////////////
LRESULT CALLBACK WindowProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam );
string TroopDistToString(void);


int WINAPI WinMain(HINSTANCE hInstance,
               HINSTANCE hPrevInstance,
               LPSTR lpCmdLine,
               INT)
{
// Game Window Class
WNDCLASSEX wc;

ZeroMemory(&wc, sizeof(WNDCLASSEX));

wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = ( (HBRUSH)COLOR_WINDOW );
wc.lpszClassName = "Game Window";

RegisterClassEx(&wc);
HWND hWnd = CreateWindow( "Game Window", "Projectile Motion",
                          WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
                          0,  0,
                          CLIENT_WIN_WIDTH, CLIENT_WIN_HEIGHT,
                          NULL, NULL, hInstance, NULL );


ShowWindow( hWnd, SW_SHOWDEFAULT );
UpdateWindow(hWnd);
Game theGame(hWnd);


MSG msg;
ZeroMemory( &msg, sizeof(msg) );

while(TRUE)
{
    while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    if(msg.message == WM_QUIT)
        break;

    theGame.Run();
}

UnregisterClass( "Game Window", wc.hInstance );

//////////////////////// Possibly unneeded /////////////////////////
ZeroMemory( &hStaticTxtBoxDistance, sizeof(hStaticTxtBoxDistance) );
ZeroMemory( &hStaticTxtBoxAngleCap, sizeof(hStaticTxtBoxAngleCap) );
ZeroMemory( &hTextBoxAngle,         sizeof(hTextBoxAngle)         );
ZeroMemory( &hStaticTxtBoxVelocCap, sizeof(hStaticTxtBoxVelocCap) );
ZeroMemory( &hTextBoxVeloc,         sizeof(hTextBoxVeloc)         );
ZeroMemory( &hButton,               sizeof(hButton)               );
ZeroMemory( &wc,                    sizeof(wc)                    );
////////////////////////////////////////////////////////////////////
return msg.wParam;
}

LRESULT CALLBACK WindowProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
{
HDC hdcStatic = ( (HDC)wParam );
HBRUSH hbrBkgnd = NULL;
switch(message)
{
case WM_CREATE:
    /////////////////////////////////// Take Shot Controls //////////////////////////////////

    // Take Shot Button
    hButton = CreateWindow( "Button", "Take Shot",
                            WS_VISIBLE | WS_CHILD,
                            CONTROL_START_X, 10, 
                            CONTROL_WIDTH, CONTROL_HEIGHT,
                            hWnd, ( (HMENU)ID_BUTTON ), NULL, NULL );

    /////////////////////////////////// Velocity Controls ///////////////////////////////////

    // Velocity Textbox
    hTextBoxVeloc = CreateWindow( "Edit", blankBox.c_str(),
                                  WS_VISIBLE | WS_CHILD | WS_BORDER,
                                  CONTROL_START_X, VELOC_TB_START_Y, 
                                  CONTROL_WIDTH, CONTROL_HEIGHT,
                                  hWnd, ( (HMENU)ID_VELOC_TB ), NULL, NULL );

    //////////////////////////////////// Angle Controls /////////////////////////////////////

    // Angle Textbox
    hTextBoxAngle = CreateWindow(  "Edit", "Angle TB" ,
                                  WS_VISIBLE | WS_CHILD | WS_BORDER,
                                  CONTROL_START_X, ANGLE_TB_START_Y, 
                                  CONTROL_WIDTH, CONTROL_HEIGHT,
                                  hWnd, ( (HMENU)ID_ANGLE_TB ), NULL, NULL );

    break;
    ///////////////////////////////// End Create Controls ///////////////////////////////////

    /////////////////////////////// User Actions On Controls ////////////////////////////////
case WM_COMMAND:
    switch(LOWORD(wParam))
    {
        //************************* Case statments tried in attempt to get the text box to 
        //************************* clear upon clicking on it and still have it usable afterwards
    //case ID_VELOC_TB:
        //  SendMessage( hWnd, WM_SETTEXT, ( (WPARAM)hWnd ), ( (LPARAM)hTextBoxVeloc ) );
//          SetWindowText( hTextBoxVeloc, (LPCSTR)blankBox[1] );
        //SetWindowText( hTextBoxVeloc, blankBox.c_str() );
        //GetLastError();
          //break;

        //  /*case WM_SETTEXT:
        //  SetWindowText( hTextBoxVeloc, TEXT( "" ) );
        //  break;
        //****************************************************************************************

    }
    // End user control action
    break;

//case WM_SETTEXT:
//  SetWindowText( hTextBoxVeloc, TEXT( blankBox.c_str() ) );
//  break;

case WM_DESTROY:
    {
        PostQuitMessage(0);
        return 0;
    } break;
}

return DefWindowProc( hWnd, message, wParam, lParam );
}

同样,除了SetWindowText之外,所有这些都运行良好。我可以在文本框中输入我想要的任何内容,最多10个字符(我认为这是我的限制),我可以接受输入并通过函数运行它来检查它是否是数字,我可以验证输入该函数并将其插入变量以运行游戏,我只是不能让SetWindowText与任何文本框一起使用。由于原帖我也尝试过非空字符串,我注意到它没有输入我输入的内容。当我点击文本框(即使我想要触发SetWindowText)时,它会清除文本框的内容,就像它正在工作但是它不会向其内容添加任何内容并打破文本框和游戏,尽管一旦我尝试做另一个输入,游戏就会中断,它会继续运行到我尝试的下一个输入。

1 个答案:

答案 0 :(得分:1)

TEXT()宏仅适用于文字,因此TEXT( troopDistStr.c_str() )之类的语句无效。只需按原样传递c_str(),它将编译或不会:

hStaticTxtBoxDistance = CreateWindow( ..., troopDistStr.c_str(), ... );

同样适用于TEXT( (LPCSTR)blankBox[1] )

SetWindowText( hTextBoxVeloc, blankBox.c_str() );

troopDistStrblankBox被声明为string,它使用char数据,因此只有在未为您的项目定义UNICODE时才会编译此类语句,以便CreateWindow()映射到CreateWindowA()而不是CreateWindowW()(您在不使用UnregisterClass()的情况下调用TEXT()表示您没有编译Unicode)

<强>更新

SendMessage( hWnd, WM_SETTEXT, ( (WPARAM)hWnd ), ( (LPARAM)hTextBoxVeloc ) )无效,您传递的HWND需要char*。您可能打算通过velocEntered而不是hTextBoxVeloc

SetWindowText( hTextBoxVeloc, (LPCSTR)blankBox[1] )无效,您将单个char值类型转换为char*指针。您需要使用&blankBox[0],但是当blankBox被声明为char[1]时,这将无效,因为没有空余的终止符,并且blankBoxstring时仅当它不为空时才声明为SetWindowText( hTextBoxVeloc, blankBox.c_str() )

只要blankBox是有效的string实例且未损坏,

{{1}}将始终正常工作。