2014-08-28 3 views
0

Я работаю над небольшим графическим калькулятором, и мне нужно добавить что-то к содержимому элемента управления редактирования. Функция, которую я использую в настоящее время:Как добавить символ [256] в содержимое элемента управления редактированием?

int CharControl = 256; 

void AddToEditMainText(char WhatToAdd[CharControl]) { 
    char CurrText[CharControl] = ""; 
    GetDlgItemText(MainWindow, EDIT_MAIN, CurrText, CharControl); 
    char NewText[CharControl] = ""; 
    malloc(strlen(NewText) + strlen(WhatToAdd) + 1); 
    strcpy_s(NewText, CurrText); 
    strcat_s(NewText, WhatToAdd); 
    SendMessage(EditMain, WM_SETTEXT, NULL, LPARAM((LPCSTR)&NewText)); 
} 

Я относительно не знаком с C++, так что это мой первый проект GUI. Любая помощь приветствуется. Благодарю.

+0

'WM_SETTEXT' заменит все содержимое. Чтобы добавить, вы можете поместить курсор в конец с помощью 'EM_SETSEL', а затем использовать' EM_REPLACESEL' для добавления. –

+0

Не используйте Code :: Blocks - это печально известный для использования злополучных значений по умолчанию. Windows NT была UTF-16 с момента ее создания. Не используйте 'char' - 'wchar_t', где он находится. – IInspectable

+0

Я не использую code :: blocks, я использую visual studio 2013. – Forrest4096

ответ

1

Давайте изменим несколько вещей :

void AddToEditMainText(char *WhatToAdd) 

В контексте параметров функции массив символов и указатель - это одно и то же. Даже если переданный параметр является массивом символов заданной длины, это не имеет значения, поэтому давайте не будем путать вещи.

Но мы можем сделать еще лучше. Этот вопрос отмечен как C++, а не C. В C++ мы хотели бы думать, что мы немного продвинулись по сравнению с низкоуровневым байтом. Когда мы говорим строки, теперь мы говорим зЬй :: строка:

void AddToEditMainText(const std::string &WhatToAdd) 

Я не очень хорошо знаком с MS-Windows API, но это кажется очевидным, что «GetDlgItemText» является функцией C API, который вытягивает текст из существующего диалогового элемента управления. Не уверен, что вам гарантировано, что возвращенная строка будет меньше или будет усечена до 256-байтового буфера. Это на самом деле важный момент, но для вводной среды для C++ это не важно.

Буфер символов, используемый GetDlgItemText(), является таким ... C-ish. Буквенный буфер является такой странной концепцией в C++. После GetDlgItemText возвращается, давайте не будем тратить время, и получить его в хороший, довольно, станд :: строка:

std::string CurrTextStr=CurrText; 

Теперь, опять же, в C++ мы не должны беспокоиться о мелочах, как выделение памяти , и убедитесь, что освободили его после использования. std :: string сделает это для нас:

std::string combinedString=CurrTextStr + WhatToAdd; 

Не так ли? Нет необходимости вычислять размеры различных буферов. Это так ... в прошлом веке. Мы находимся в современной эпохе, где оператор «+» сделает это за нас. И, наконец, так как SendMessage() является еще одной причудливой C библиотеки API, и мы должны говорить до его уровня, я полагаю ...

SendMessage(EditMain, WM_SETTEXT, NULL, LPARAM((LPCSTR)combinedString.c_str())); 

Ох, и не забудьте воткнуть «#include < строка > "где-то наверху, чтобы вывести определение std :: string.

+0

Это приведение к 'LPCSTR' просто вызывает мое подозрение, пока я не пойму, что это просто кастинг того же типа, что и операнд. – chris

+0

Использование ссылок на объекты C++ в интерфейсе - это не то, что я бы назвал * «еще лучше» *. Это серьезно ограничивает применимость. Вы только что перешли из * ", можно вызвать только из любого языка программирования в юниверсе« * to * »использовать только с C++, используя этот конкретный компилятор и этот конкретный CRT, и предоставлять ** точно ** эти параметры компилятора» * , Просто оставьте его в 'const char *' и перейдите. – IInspectable

2

Вы не назначаете результат malloc() на все, чтобы вы пропускали память. Вы должны делать что-то больше, как это вместо:

void AddToEditMainText(char *WhatToAdd) 
{ 
    int iLen = GetWindowTextLen(EditMain) + strlen(WhatToAdd) + 1; 
    char *NewText = malloc(iLen); 
    if (NewText) 
    { 
     GetWindowText(EditMain, NewText, iLen); 
     strcat_s(NewText, iLen, WhatToAdd); 
     SetWindowText(EditMain, NewText); 
     free(NewText); 
    } 
} 

Я хотел бы предложить другой подход, который не требует от вас, чтобы получить текущий текст перед добавлением к нему:

void AddToEditMainText(char *WhatToAdd) 
{ 
    DWORD dwStart, dwEnd; 
    SendMessage(EditMain, EM_GETSEL, WPARAM(&dwStart), LPARAM(&dwEnd)); 
    int iLen = GetWindowTextLength(EditMain); 
    SendMessage(EditMain, EM_SETSEL, iLen, iLen); 
    SendMessage(EditMain, EM_REPLACESEL, TRUE, LPARAM(WhatToAdd)); 
    SendMessage(EditMain, EM_SETSEL, WPARAM(dwStart), LPARAM(dwEnd)); 
} 
+0

Аналогичным образом, на более позднем этапе мне придется закодировать какой-то метод обратного пробела. Я нашел использование вашего метода EM_SETSEL и EM_REPLACESEL полезным, так как есть способ сделать функцию backspace с помощью этого? – Forrest4096

+0

Просто используйте 'EM_SETSEL', чтобы выбрать последний символ, а затем' EM_REPLACESEL' с пустой строкой. –