编辑框SetWindowText打破框

Edit box SetWindowText breaking the box

本文关键字:SetWindowText 编辑      更新时间:2023-10-16

(对长度表示抱歉)我遇到的问题是文本框控件上的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);
        }

我尝试使用字符串和字符数组,试图避免不可变的字符串,以及只是插入一个文本(")直接到SetWindowText调用,但没有工作

我正在做这个项目作为我的c++类的荣誉项目,所以我从Win32和DirectX中自学了这个项目中的一切,所以如果有一个非常明显的错误,我很抱歉。除了错误,我还想知道如何在退出时清理为窗口分配的内存。我在WinMain结束时为我创建的所有窗口设置了一组zerommemory调用,因为在不清理内存的情况下结束程序感觉很奇怪,但我真的没有看到其他人有这些,所以请告诉我是否不需要这样做,或者是否有不同的方法。

我有问题的代码:

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),它清除文本框的内容,就像它正在工作,但然后它不添加任何内容,打破文本框和游戏,虽然游戏只打破一次我尝试做另一个输入,它将继续运行到下一个输入我尝试。

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]时,这将不起作用,因为没有空终止符的空间,并且当blankBox被声明为string时,只有当它不为空时才会起作用。

SetWindowText( hTextBoxVeloc, blankBox.c_str() )将始终工作良好,只要blankBox是一个有效的string实例,没有损坏。