2013-05-02 17 views
7

Bir iletişim kutusunun içindeki düzenleme denetimine metin eklemeye çalışıyorum. Doğru eklemek için _tcscat_s alamıyorum. Çöküyor ve arabelleğin çok küçük veya boş sonlandırılmış bir dizeyle ilgili bir şey söylediğini söylüyor.Win32 - Bir Düzenle Denetimine metin ekleme

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) 
{ 
    return DialogBox(hInstance, MAKEINTRESOURCE(IDD_MAIN), NULL, DlgProc); 
} 

BOOL CALLBACK DlgProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) 
{ 
    switch(Message) 
    { 
     case WM_INITDIALOG: 
      OpenAndReadFile(hwnd); 
      return TRUE; 
     case WM_COMMAND: 
      switch(LOWORD(wParam)) 
      { 
       case IDSTART: 
        EndDialog(hwnd, IDSTART); 
        break; 
       case IDQUIT: 
        EndDialog(hwnd, IDQUIT); 
        break; 
      } 
      break; 
     case WM_CLOSE: 
      EndDialog(hwnd, 0); 
      break; 
     default: 
      return FALSE; 
    } 
    return TRUE; 
} 

BOOL OpenAndReadFile(const HWND &hwnd) 
{ 
    // Open the file 

    HANDLE hFile; 
    hFile = CreateFile(TEXT("sites.txt"), // file to open 
         GENERIC_READ,   // open for reading 
         FILE_SHARE_READ,  // share for reading 
         NULL,     // default security 
         OPEN_EXISTING,   // existing file only 
         FILE_ATTRIBUTE_NORMAL, // normal file 
         NULL);     // no attr. template 

    if (hFile == INVALID_HANDLE_VALUE) 
    { 
     SetDlgItemText(hwnd, IDC_OUTPUT, TEXT("Error: File could not be opened\r\n")); 
     return FALSE; 
    } 
    else 
     SetDlgItemText(hwnd, IDC_OUTPUT, TEXT("sites.txt opened\r\n")); 

    AppendText(hwnd, TEXT("TEXT")); 

    // Read data from file 

    const DWORD BUFFERSIZE = GetFileSize(hFile, NULL); 
    char *ReadBuffer = new char [BUFFERSIZE](); 
    DWORD dwBytesRead = 0; 

    // read one character less than the buffer size to save room for the 
    // terminate NULL character. 
    //if (FALSE == ReadFile(hFile, ReadBuffer, BUFFERSIZE - 1, &dwBytesRead, NULL)) 
    { 

    } 

    return TRUE; 
} 

void AppendText(const HWND &hwnd, TCHAR *newText) 
{ 
    // get size to determine buffer size 
    int outLength = GetWindowTextLength(GetDlgItem(hwnd, IDC_OUTPUT)); 

    // create buffer to hold current text in edit control 
    TCHAR * buf = (TCHAR *) GlobalAlloc(GPTR, outLength + 1); 

    // get existing text from edit control and put into buffer 
    GetDlgItemText(hwnd, IDC_OUTPUT, buf, outLength + 1); 

    // append the newText to the buffer 
    _tcscat_s(buf, outLength + 1, newText); 

    // Set the text in the dialog 
    SetDlgItemText(hwnd, IDC_OUTPUT, buf); 
} 
+0

:

void AppendText(const HWND &hwnd, TCHAR *newText) { // get edit control from dialog HWND hwndOutput = GetDlgItem(hwnd, IDC_OUTPUT); // get the current selection DWORD StartPos, EndPos; SendMessage(hwndOutput, EM_GETSEL, reinterpret_cast<WPARAM>(&StartPos), reinterpret_cast<WPARAM>(&EndPos)); // move the caret to the end of the text int outLength = GetWindowTextLength(hwndOutput); SendMessage(hwndOutput, EM_SETSEL, outLength, outLength); // insert the text at the new caret position SendMessage(hwndOutput, EM_REPLACESEL, TRUE, reinterpret_cast<LPARAM>(newText)); // restore the previous selection SendMessage(hwndOutput, EM_SETSEL, StartPos, EndPos); } 
ShrimpCrackers

+0

Neden onu kullanıyorsunuz? Aynı algoritmayı kullanmak için, metni bir 'std :: string' içine yükleyin, ona ekleyin ve geri kaydedin. En azından C++ 11'de, verilerin bitişik olduğu garanti edilir. C++ 11 kullanmıyorsanız, std :: vector işlevi metni yüklemek için hemen hemen aynı şekilde çalışır. Alternatif olarak (ve muhtemelen daha iyi), [bu tekniği] kullanın (http://stackoverflow.com/a/12538062/962089). Bunun için hafıza yönetimi yok. Ekleme konusunda endişelenme. Sadece kullanımı kolay. – chris

+0

@ShrimpCrackers: '_tcscat_s()' Eklenen metin arabelleğin sınırlarını aşarsa arabelleği büyütmez. '_tcscat_s()', arabellek boyutunu belirtmek için bir parametreye sahiptir, bu yüzden çok uzun olursa, birleştirilmiş metni keser. Bu nedenle, içine metin koymaya başlamadan önce arabelleği gereken son boyuta ayırmanız gerekir. –

cevap

14

GetWindowTextLength() metinde TCHAR elemanların sayısını döndürür, ancak GlobalAlloc() bir bayt yerine saymak bekliyor. Unicode için derliyorsanız, TCHAR, 1 bayt değil 2 bayttır, ancak bunu dikkate almıyorsunuz. Ayrıca, varolan metni ve eklenmiş yeni metni de tutacak kadar büyük bir arabellek ayırmıyorsunuz. Ayrıca, ayırdığınız belleği de sızdırıyorsunuz.

bu deneyin: Alternatif

void AppendText(const HWND &hwnd, TCHAR *newText) 
{ 
    // get edit control from dialog 
    HWND hwndOutput = GetDlgItem(hwnd, IDC_OUTPUT); 

    // get new length to determine buffer size 
    int outLength = GetWindowTextLength(hwndOutput) + lstrlen(newText) + 1; 

    // create buffer to hold current and new text 
    TCHAR * buf = (TCHAR *) GlobalAlloc(GPTR, outLength * sizeof(TCHAR)); 
    if (!buf) return; 

    // get existing text from edit control and put into buffer 
    GetWindowText(hwndOutput, buf, outLength); 

    // append the newText to the buffer 
    _tcscat_s(buf, outLength, newText); 

    // Set the text in the edit control 
    SetWindowText(hwndOutput, buf); 

    // free the buffer 
    GlobalFree(buf); 
} 

: o pencerenin metin çok verimsiz bir yoldur değiştirilmesi sonra, belleğe pencerenin mevcut metni alma buna ekleme ve, sözlerimle

#include <vector> 

void AppendText(const HWND &hwnd, TCHAR *newText) 
{ 
    // get edit control from dialog 
    HWND hwndOutput = GetDlgItem(hwnd, IDC_OUTPUT); 

    // get new length to determine buffer size 
    int outLength = GetWindowTextLength(hwndOutput) + lstrlen(newText) + 1; 

    // create buffer to hold current and new text 
    std::vector<TCHAR> buf(outLength); 
    TCHAR *pbuf = &buf[0]; 

    // get existing text from edit control and put into buffer 
    GetWindowText(hwndOutput, pbuf, outLength); 

    // append the newText to the buffer 
    _tcscat_s(pbuf, outLength, newText); 

    // Set the text in the edit control 
    SetWindowText(hwndOutput, pbuf); 
} 

bir düzenleme denetimine metin eklemek için yerine EM_REPLACESEL mesajı kullanın: Bir birleştirme yaparken _tcscat_s gerekli boşluk eklenir varsayarak edilmiştir

string buffer = "append this!" 
    HWND hEdit = GetDlgItem (hDlg, ID_EDIT); 
    int index = GetWindowTextLength (hEdit); 
    SetFocus (hEdit); // set focus 
    SendMessageA(hEdit, EM_SETSEL, (WPARAM)index, (LPARAM)index); // set selection - end of text 
    SendMessageA(hEdit, EM_REPLACESEL, 0, (LPARAM)buffer.c_str()); // append! 
+0

Verimsiz ve sadece daha fazla vidalanma olasılığı ekler Bir şey, işaret ettiğin tüm sorunlarda oldukça belirgindir. – chris

+0

Teşekkürler, Remy. Harika çalışıyor. Win32 api için yeni olmak, bu son örnek hakkında üç sorum var. (1) hwndOutput ataması gerekli midir? Diyalog kontrolüne bir fonksiyon parametresi olarak geçtiğimi sanıyordum. DlgProc() hwnd başka bir şey için bir tanıtıcı işlevi var mı? (2) WPARAM ve LPARAM’da neden reinterpret_cast? (3) OutLength neden WPARAM ve LPARAM parametrelerine gönderilmelidir? – ShrimpCrackers

+1

1) 'EM _...' mesajları düzenleme denetimine doğrudan gider, böylece HWND'yi bir kez yakalayıp bunu birden çok kez kullanmanın anlamlı olduğunu görürsünüz. DlgProc() HWND, üst iletişim kutusudur. 2) 'reinterpret_cast', C++ 'nın tip-güvenli, tamamlayıcı-doğrulanmış yoludur, bir tamsayıya bir işaretçi (tam tersi) ve tam tersi (diğer şeyler arasında). 3) [belgeleri oku] (http://msdn.microsoft.com/en-us/library/windows/desktop/bb761661.aspx). 4) OpenAndReadFile() 'da bir bellek sızıntınız var. –