понедельник, 31 марта 2008 г.

C размаху головой об стену бьюсь

Начал делать опции, диалог набросал - вполне нормально получилось. А дальше траблы:

  1. Контрола для ввода горячей клавиши в wxWidgets нету. Из сторонних решений есть keybinder, но как я понять это достаточно мощный комбаин предназначенный немного для другого. Но попробую поковырять. Откровенно говоря подозреваю что такой контрол и ручками можно написать достаточно просто или вообще виндовый заюзать (хотя не уверен что это можно).
  2. Чекбоксы не поддерживают мультилайн. Хреново. \r\n не работает, хотя это было бы тоже не выход а костыли. Почему то у wxStaticText есть Wrap, а чекбокса нету.

 

Да если вас заинтересовал первый пункт, то наверное будет интересно узнать, что возможности сделать system wide hotkey под linux'om тоже нету. Разработчики библиотеки говорят - что линукс не дает такого апи. Хотя ходят слухи, что какие обходные пути есть. Дожевем до линукса посмотрим.

четверг, 27 марта 2008 г.

GetForbiddenChars() -> ReplaceForbiddenCharsInFileName()

Оказалось, что если в диалог открытия файла в качестве дефолтного имени передать имя содержащее запрещенные символы - он вываливается с ошибкой так и не открывшись. Проверил под MFC, тоже не фонтан,  просто молча не открывается. Так что надо запрещенные символы убирать. Удивился, что это не делает сама библиотека, перед тем как сунуть имя в системный диалог. Полез искать функцию которая могла бы это сделать. Удивился еще больше - похоже такой функции нет(или я не нашел).

wxFileName::GetForbiddenChars() есть, а обработать имя нечем. Написал свою.

/*static*/

wxString & BegUtils::ReplaceForbiddenCharsInFileName(wxString & name, const wxString ch/*=wxT("_")*/)

{

    wxString forbidden = wxFileName::GetForbiddenChars();

    int size=forbidden.Length();

    for (int i=0; i<size; ++i)

          name.Replace( wxString(forbidden[i]), ch,

true);

   return name;

}

 

P.S. Кстати если в диалоге выбора папки - выбрать что-нибудь типа Мой Компьюте или Сетевое Окружение и нажать ОК, то диалог ввернет wxID_CANCEL. Он то вроде и правильно, нельзя же в эти папки писать - но пользователь может и не понять. Под MFC возращает id_ok и кривой путь, в результате получается запись в корень с:

суббота, 22 марта 2008 г.

Антиспамеры зло

Чего-то там правят в списках рассылки wx'совских, перенесли на новый сервер, поставили SpamAssassin.  Теперь все мои письма Blocked by SpamAssassin. Обращения на форум шадонета не помогло, письмо лично тому чуваку который анонсировал изменения в майл листах тоже без ответа. Так что теперь чукча не писатель, чукча читатель.

четверг, 6 марта 2008 г.

Грузим текстовый файл

Задача: есть wxTextCtrl, пользователь должен уметь загружать в него свои текстовые файлы для просмотра и редактирования, своего рода notepad. Файлы у пользователя могут быть в ANSI, utf-8 и в одном из двух юникодов.

Есть wxTextCtrl::LoadFile() - думаю зашибись, повезло. Тестирую, юникод\утф-8 грузит, ANSI грузит только если там одни английские символы, если есть русские обламывается. Нахожу? что проблема в дебрях библиотеки, в попытке грузить файл как wxFFile::ReadAll(wxString * str, wxMBConv& conv = wxConvUTF8)

Спрашиваю в wx-dev@, вот ответ

TN> Is this a bug? If no, is there a any way to load ANSI files in unicode
TN> build?

Yes, use wxCSConv(wxFONTENCODING_CP1251) instead of default wxConvAuto
which only handles UTF-x encodings in 2.8 (in the trunk it falls back to
the system default encoding if the input doesn't seem to be in UTF-8, but
not in 2.8).

Баг это или нет, я так и не понял. Но понял что wxTextCtrl::LoadFile() использовать нельзя, так как кодировку там задать нет возможности. Пришлось использовать напрямую wxFFile, с шаманством. Вот функция для загрузки файла

bool BegUtils::ReadFileToString(const wxString & FileName, wxString & Data)

{

wxFFile file(FileName);

if (!file.IsOpened() ) return false;

// пытаемся читать файл подразумевая что он юникодный

if (!file.ReadAll(&Data)) return false;

if (Data.IsEmpty() && file.Length()>0)

{ // Если строка пустая и длина у файла есть - то он наверняка был анси, читаем как анси

file.Seek(0);

if (!file.ReadAll(&Data, *wxConvCurrent)) return false;

}

return true;

}


Вроде как работает, правда будут проблемы при загрузки пустых юникодных файлов - на экране будет мусор (BOM), можно конечно проверять загруженную строку на равенство одному из них, но я забил.

Подозреваю что это довольно кривой метод, поэтому если кто знает как решить задачу "правильно", с удовольствием послушаю.

понедельник, 3 марта 2008 г.

Легким движением руки брюки превращаются... (опять поиск и замена wxTextCtrl)

Я уже давал ссылку на мою статью про написание Find & Replace для wxWidgets-приложений. Тот код я начинал писать для wxTextCtrl'a со стилем wxTE_RICH, а закончил и окончательно тестировал на wxRichTextCtrl'e. Сейчас я отказался от использования wxRichTextCtrl (только если вдруг его допишут до юзабельного состояния), и вернулся на самый что не на есть простой виндовый эдит, тот который в нотепаде. Пришлось править код поиска и замены.  Если вам нужен код для поиска и замены в *обычном* wxTextCtrl (без  wxTE_RICH), то правьте код из статьи вместе со мной. Пока я нашел вот что.

1. Выкидываем или убираем под дефайн следующую строчку

#ifdef

WeUseWXRichTextCtrl

//If we have not selection, wxTextCtrl return StartFromBack=StartFromForward=Current_Insertion_Point, but wxRichTextCtrl return -2,-2

if (StartFromBack<0) StartFromBack=StartFromForward=m_Note->GetInsertionPoint();

#endif

2. Дальше оказывается что ищет криво, причина находится в документации. Перед тем как считать startPos и endPos, добавляем следующий код (изврат конечно, но что делать, кому сейчас легко?):

#ifdef WeUseWXTextCtrl

#ifdef

__WIN32__

// проблемма с wxTextCtrl - The multiline text controls always store the text as a sequence of lines separated by \n characters, i.e. in the Unix text format even on non-Unix platforms. This allows the user code to ignore the differences between the platforms but at a price: the indices in the control such as those returned by GetInsertionPoint or GetSelection can not be used as indices into the string returned by GetValue as they're going to be slightly off for platforms using \r\n as separator (as Windows does), for example.

m_foundPos+=(string.Left(m_foundPos)).Replace(wxT(

"\n"), wxT("\n")); // Returns the number of replacements made.

#endif

#endif

3. В OnReplace убираем или выносим под ифдеф 1 строчку.

if (SelText==FindText)

{

#ifdef

WeUseWXRichTextCtrl

m_Note->DeleteSelection(); // this line is needed only for wxRichTextCtrl and needed not for wxTextCtrl

#endif

m_Note->WriteText(m_findData.GetReplaceString());

}

В итоге брюки превращаются...

Теперь вроде все ок, но если что еще найду - напишу.

суббота, 1 марта 2008 г.

Русский форум по wxWidgets

The wxWidgets forum has opened 3 sub forums for our international wx
friends. In the past it had appeared to us that non-native speakers
can't express their problems with wxWidgets very well which can
increase frustration unnecissarily. So we decided to open a Chinese,
Russian and French sub forum to begin with, and if needed, will open
some more for other languages. If English is not your first language
and you're still strugging a bit to explain exactly what your problems
are, go take a look at http://wxforum.shadonet.com/



Вообщем теперь есть русский подфорум по wxWidgets на шадонете - общайтесь. Ура.