На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Правила раздела Visual C++ / MFC / WTL (далее Раздела)
1) На Раздел распространяются все Правила Форума.
2) Перед тем, как создать новый топик, убедитесь, что Вы читали Правила создания тем в Разделе.
3) Вопросы, не связанные с программированием (настройки MS Visual Studio, книги, библиотеки и т.д.),
обсуждаются в разделе C/C++: Прочее
4) Вопросы разработки .NET (Windows Form, C++/CLI и т.п.) приложений на Visual C++/C# обсуждаются в разделе .NET.
5) Нарушение Правил может повлечь наказание со стороны модераторов.

Полезные ссылки:
user posted image FAQ Раздела user posted image Обновления для FAQ Раздела user posted image Поиск по Разделу user posted image MSDN Library Online
Модераторы: ElcnU
Страницы: (2) [1] 2  все  ( Перейти к последнему сообщению )  
> Юникод и консольное приложение , Мозги плавятсо...
    Пишу сейчас мега-микропрогу: MkScreens :)

    Народ заказал дичь то есть Юникод - хотца китайко-японские ироглифы в именах файлов, чтобы кушало.

    Ну - народ просит, значит сделаем. #define UNICODE, в нескольких десятках мест заменить CreateFile на CreateFileW, main на wmain, немного геморроя с переписыванием старенькой либы для разбора ключей командной строки и перевод эксцепшенов в используемой ДДЛи на Юникод...

    А вот теперь собственно к вопросам, от которых голова пухнет.

    Прога по задумке должна работать (и пока работает :)) и в линейке НТ, и 9х. Спрашивается: как замутить такую ассоциацию на неё в реестре, чтобы гарантировано передавались имена файлов в Юникоде (даже если символы в их составе не входят в текущую раскладку ANSI)?

    Следующий вопрос. Хоть я и не добился от МСДН ответа, но мне кажется, что в функцию SetConsoleOutputCP под линейкой НТ можно передать как кодовую страницу Юникод. Я прав, или нет?

    Если я таки прав, то как заюзать в таком случае потоковые классы типа wcout под Win9x (пока вывод заточен на них, т.к. я замутил очень удобные ИМХО манипуляторы для изменения цвета текста в консоли - Что-то туплю по поводу ostream_withassign и консоли )? Если для 8-битной версии я могу с успехом использовать такой примитивнейший костыль:

    ExpandedWrap disabled
      class OnTheFlyOEM {
        LPSTR lpszContainer;
      public:
        OnTheFlyOEM(LPCSTR lpszIn){
          lpszContainer = strdup(lpszIn);
          CharToOem(lpszContainer, lpszContainer);
        }
        ~OnTheFlyOEM(){
          if(lpszContainer) free(lpszContainer);
        }
        operator LPCSTR () const {
          return (LPCSTR)lpszContainer;
        }
      };
       
      cout << OnTheFlyOEM(lpszFileName) << endl;


    То для Юникодного потока это, мягко говоря, не прокатит :(

    Делать две версии проги (через условную компиляцию), равно как и мутить варианты типа:

    ExpandedWrap disabled
      if(bIsUnderNTAndUnicodeConsole)
        wcout << lpszFileName << endl;
      else
        cout << OnTheFlyOEM(lpszFileName) << endl;


    что-то не хочется :(

    Можно, конечно, написать свой класс для вывода на консоль, принимающий вывод как Юникодный, так и не Юникодный, и по ситуации делающий необходимые преобразования кодировок... Но неужели всё так запущено и ничего нельзя сделать попроще?
    Сообщение отредактировано: barazuk -
      Цитата barazuk @
      Прога по задумке должна работать (и пока работает ) и в линейке НТ, и 9х.


      Даже я отказался от поддержки 9x... :) 8 лет прошло.

      Цитата barazuk @
      в нескольких десятках мест заменить CreateFile на CreateFileW


      Зачем?

      Цитата barazuk @
      Спрашивается: как замутить такую ассоциацию на неё в реестре, чтобы гарантировано передавались имена файлов в Юникоде (даже если символы в их составе не входят в текущую раскладку ANSI)?


      Эм. А разве ключи определяют набор символов?

      Цитата barazuk @
      Хоть я и не добился от МСДН ответа, но мне кажется, что в функцию SetConsoleOutputCP под линейкой НТ можно передать как кодовую страницу Юникод. Я прав, или нет?


      Юникод -- не кодовая страница. Он в себе их содержит.
        Цитата B.V. @
        Зачем?


        Потому что используются сторонние библиотеки, которые о Юникоде ни сном ни рылом. И мне гораздо проще использовать Юникод только там, где это реально нужно, чем обвязывать все вызовы конверсией и потом отлавливать баги из-за того, что где-нибудь передаётся имя файла, которое не может быть представлено в текущей кодировке ANSI.

        Цитата B.V. @
        Даже я отказался от поддержки 9x...


        Поздравляю. А у меня дома стоит как основная система. И я счастлив :)

        Цитата B.V. @
        Юникод -- не кодовая страница. Он в себе их содержит


        Не бредь. Хорошо, не кодовая страница, если тебе угодно (хотя устоявшихся русскоязычных терминов для подобных понятий всё равно не существует), а кодировка, если тебе от этого легче.

        Цитата B.V. @
        Эм. А разве ключи определяют набор символов?


        А ты считаешь, что по двойному щелчку на файле, например, в Вин98 всегда по умолчанию Юникодное имя передаётся?
        Я например не уверен. Буду проверять.


        Вообщем, спасибо за развёрнутый ответ в стиле "оно тебе не надо" :whistle:
          Цитата barazuk @
          Не бредь. Хорошо, не кодовая страница, если тебе угодно (хотя устоявшихся русскоязычных терминов для подобных понятий всё равно не существует), а кодировка, если тебе от этого легче.

          Это не может быть ему угодно. Это действительно разные вещи. UNICODE (название говорит само за себя) содержит в себе уйму всяких таблиц символов. В то время как ANSI содержит в себе только одну - заданную локализацией системы.
            Хорошо, тогда UTF8 тоже не кодовая страница по-твоему?
              Цитата barazuk @
              Хорошо, тогда UTF8 тоже не кодовая страница по-твоему?


              Отсюда и до просветления.
                Что касается вопроса. Может я тебя не правильно понял, заранее прощу прощения, но как насчет:
                ExpandedWrap disabled
                  #ifdef UNICODE
                      #define cout wcout
                  #endif
                Естественно грубо и некрасиво, но может натолкнет на мысль. ;)
                  Я мож тоже не понял ну мож поможет :lol:
                  ExpandedWrap disabled
                    #ifdef _UNICODE
                    int main()
                    #endif
                     
                    int main()
                    {
                        //to do
                        return 0;
                    }

                  Если не то то ПОРДОН!!! :wacko:
                  Сообщение отредактировано: dedok[kelev(ruso)] -
                    Цитата dedok[kelev(ruso)] @
                    Если не то то ПОРДОН!!! :wacko:

                    Определенно не то. И если будет объявлена _UNICODE, то компилятор расскажет о синтаксической ошибке. :blink:
                      Цитата ALXR @
                      Определенно не то. И если будет объявлена _UNICODE, то компилятор расскажет о синтаксической ошибке.

                      Компельни это в консоле Win32 , не какой ошибки ,мы в универи так делали для поддержание русского языка в консоле!!!
                      Сообщение отредактировано: dedok[kelev(ruso)] -
                        Цитата B.V. @
                        Отсюда и до просветления.


                        О, да!
                        Цитата
                        Использование различных кодовых страниц создаёт много неудобств как для пользователей, так и для программистов. При попытке прочесть текстовый файл при помощи кодовой страницы, несовместимой с той в которой он был создан, возникают крокозябры. В последние годы получил широкое распространение Unicode как альтернатива традиционным кодовым страницам


                        Уровень изложения просто потрясает... Хорошо хоть внизу упомянули:

                        Цитата
                        Это незавершённая статья о компьютерном программном обеспечении.
                        Вы можете помочь проекту, исправив и дополнив её.


                        В чём тут просветление - большая загадка.

                        А теперь обратимся к первоисточнику - МСДН:

                        Цитата
                        BOOL SetConsoleOutputCP(
                        UINT wCodePageID // code page to set
                        );


                        Parameters
                        wCodePageID
                        Specifies the identifier of the code page to set. The identifiers of the code pages available on the local computer are stored in the registry under the following key.

                        HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\CodePage


                        Т.е. по версии мелкомягких (без лишних философствований), кодовая страница - это то, что перечислено в указанном ключе реестра (:) ;)). Имеющий глаза, легко может увидеть там по ХРюнделем и UTF-7 (65000), и UTF-8 (65001). Более того, если написать такой мегакод:

                        ExpandedWrap disabled
                              cout << GetConsoleOutputCP() << endl;
                              SetConsoleOutputCP(65001);
                              cout << GetConsoleOutputCP() << endl;


                        То, как ни странно, на выходе получим:
                        Цитата
                        866
                        65001


                        И на фоне восхищённых визгов об тотальной 32-битности и юникодности ХП можно было бы ожидать, что оно и работать будет - однако же нет, юникодные консольные функции являются полной профанацией - вместо того, чтобы реально использовать возможность вывода в консоль трутайпными юникодными шрифтами, добрые дядьки тупо делают преобразование Юникод -> OEM. Что весьма и весьма печально...

                        Добавлено
                        Хотя с другой стороны, один из вопросов снимается: как не пинай консоль, а вроке как ничего, окромя текущей ОЕМ-раксладки, в неё не выведешь.
                          Хотел бы я посмотреть, как в текстовом режиме можно было бы расширить ASCII-таблицу до юникода. :lol: Шрифт еще на свой поменять можно...

                          Кстати, о UTF-7(8): Это и близко не юникод и не анси - это вообще, отдельная фигня.
                            Цитата ALXR @
                            Хотел бы я посмотреть, как в текстовом режиме можно было бы расширить ASCII-таблицу до юникода. Шрифт еще на свой поменять можно...


                            Мать... Опять путаем мягкое с тёплым. При чём тут текстовый режим к консоли? Или кто-то мне хочет сказать, что Вин32 консольное приложение прямо лезет к видеопамяти в текстовом режиме? :wacko:

                            Функции для вывода в консоль Юникодные (типа) - есть.
                            Шрифты Юникодные - есть.

                            Вопросы "совместимости" можно было бы и похерить - ведь, к примеру, размеры "консоли" вполне спокойно устанавливаются произвольным образом - никто ведь не делает трагедии из того, что при запуске ДОСовских прог (или просто при нажатии Alt+Enter) консоль какого-нибудь дикого размера типа 127 * 51 "прыгает" в поноэкранный режим и меняет размер на стандартный 80 * 25?

                            Цитата ALXR @
                            Кстати, о UTF-7(8): Это и близко не юникод и не анси - это вообще, отдельная фигня.


                            Это способ кодирования 16-битного Юникода в 8-битные последовательности.

                            Короче: всё! Замяли вопрос! Независимо от того, как это называть, Юникода в консоли не прикрутили. Не захотели связываться. Точка.

                            А имеющиеся Юникодные функции для вывода в консоль на самом деле тупые обёртки для 8-мибитных. И нафиг не нужны, по сути. Т.о. позвать CharToOem остаётся наиболее простым, переносимым и вменяемым способом вывода текста в консоль.
                              Цитата barazuk @
                              Цитата ALXR @
                              Хотел бы я посмотреть, как в текстовом режиме можно было бы расширить ASCII-таблицу до юникода. Шрифт еще на свой поменять можно...


                              Мать... Опять путаем мягкое с тёплым. При чём тут текстовый режим к консоли? Или кто-то мне хочет сказать, что Вин32 консольное приложение прямо лезет к видеопамяти в текстовом режиме? :wacko:

                              Функции для вывода в консоль Юникодные (типа) - есть.
                              Шрифты Юникодные - есть.

                              Вопросы "совместимости" можно было бы и похерить - ведь, к примеру, размеры "консоли" вполне спокойно устанавливаются произвольным образом - никто ведь не делает трагедии из того, что при запуске ДОСовских прог (или просто при нажатии Alt+Enter) консоль какого-нибудь дикого размера типа 127 * 51 "прыгает" в поноэкранный режим и меняет размер на стандартный 80 * 25?

                              Цитата ALXR @
                              Кстати, о UTF-7(8): Это и близко не юникод и не анси - это вообще, отдельная фигня.


                              Это способ кодирования 16-битного Юникода в 8-битные последовательности.

                              Короче: всё! Замяли вопрос! Независимо от того, как это называть, Юникода в консоли не прикрутили. Не захотели связываться. Точка.

                              А имеющиеся Юникодные функции для вывода в консоль на самом деле тупые обёртки для 8-мибитных. И нафиг не нужны, по сути. Т.о. позвать CharToOem остаётся наиболее простым, переносимым и вменяемым способом вывода текста в консоль.

                              Кто тут путает теплое с мягким, так это Вы. Текстовый режим в консоли предстает Вашим очам при нажатии комбинации клавиш Ctrl+Enter. Черное окошко - по сути эмуляция этого текстового режима. Кстати видеопамять (да-да, та самая, что когда-то лежала по адресу 0xb8000) также имеет место быть. Записали строчечку в консоль, извольте видеть ее в имитации видеопамяти... да-да, по тому же самому адресу - 0xb8000.

                              Функции юникодные преобразуют юникодную строку в ANSI-строку в соответствии с локализацией системы. Право неудобно было бы заниматься конвертацией юникод-строки в ANSI перед выводом ее в консоль каждый раз. Больше того(!) есть 2 типа ф-ций CharToOem() и OemToChar() - соответственно WIDE-char (CharToOemW() / OemToCharW()) и ANSI-char (CharToOemA() / OemToCharA()).

                              У текстового режима разнообразие разрешений поскуднее, конечно, чем у графического, но тоже имеет место быть. Есть и 80х50 и еще больше. И каких там только еще нет.

                              В целом вывод следующий: Будь ты хоть семи пядей во лбу, но из консоли графическую среду с поддержкой юникода и тру-тайп шрифтов не получить. Консоль - это консоль и ни граммом больше. Хочется отличиться и сделать красиво? Так вперед, сделайте свою имитацию консоли, задефайните ф-ции типа WriteConsole или перегрузите cout на вывод в свою "консоль" и будет и юникод и тру-тайп шрифты и можно даже будет цветочки в ней рисовать. И в целом не следует путать ф-ции типа Wide-char с юникод-шрифтами. <_<
                                Цитата ALXR @
                                И в целом не следует путать ф-ции типа Wide-char со юникод-шрифтами


                                Угу. Угу. То есть Юникод как бы вроде и есть, только его нет. :ph34r: Что и требовалось доказать.

                                Цитата ALXR @
                                Записали строчечку в консоль, извольте видеть ее в имитации видеопамяти...


                                Вот именно. Можно было сделать Юникодную 16-тибитную консоль. В оконном режиме - отображать во всём великолепии.

                                В полноэкранном - делать CharToOem и рисовать, что получится.

                                Не вижу никаких принципиальных проблем. Более того, можно было просто создать отдельный подвид - "чисто Юникодная консоль" - которую не давать разворачивать в полноэкранку.

                                Можно ещё кучу вариантов было бы придумать... Если бы было желание.

                                Тем более, что в ХП "загрузка в режиме консоли" - всё равно производится в графическом режиме, а уже там в окошке запускаетсяопять-таки эмуляция :)


                                Для меня просто странно при восторженных визгах о революционности, тотальноей 32-битности и юникодности без позорных пережитков прошлого, наблюдать такое убожество, когда можно было тучу более других вариантов устроить.
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0994 ]   [ 16 queries used ]   [ Generated: 20.04.24, 01:13 GMT ]