Есть ли безболезненный способ создания пользовательского интерфейса Windows в C? - PullRequest
5 голосов
/ 30 мая 2009

редактировать

хорошо, я полагаю, что С болезнен по своей природе. Просто эта часть особенно болезненна.
Кроме того, нет реальной причины, по которой я пишу только на C, кроме того, на котором я хочу писать и на котором пока разбираюсь. Я знаю, что переход с C на C ++ - это плохо, но что угодно.

А кто-нибудь знает решение моей проблемы с созданием более одного окна в программе?


Ну, я связывал C DLL с интерфейсом VB6, но - попытки передавать строки назад и вперед становились уродливыми, и казалось, что каждый раз, когда я добавляю новую функцию, все остальное сломалось бы. Итак, я подумал: зачем мне проходить через всю эту боль, просто чтобы общаться с языком, который даже больше не поддерживается? Почему бы просто не использовать эту боль для лучшего использования и научиться создавать интерфейс в C?

Ну, я начал, но я должен спросить: есть ли простой способ сделать это? Огромный оператор switch, который называется WndProc, ранит мои глаза и идет вразрез со всем, что я узнал о чистом коде (во многом как параметр 12 CreateWindowEx () или параметр 14 CreateFont ()).

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

В любом случае, мне удалось создать большую форму под названием «Главное окно!» С «Всплывающим сообщением!» Кнопка, которая работает хорошо - и это не было сложно вообще. Тогда есть «Изменить этот текст!» кнопка, которая изменяет текст в элементе управления редактирования. Чтобы это было возможно, WndProc должен знать об элементе редактирования, пока он получает сообщение WM_COMMAND от кнопки. Я не могу передать hWnd для элемента управления редактирования в него, так как я не тот, кто его вызывает, и вы не можете просто добавить аргументы в WndProc. Поэтому мне пришлось поместить элемент управления редактирования в глобальный объем.

Я хотел изменить шрифт кнопок на 13pt Tahoma - легко, правда? Конечно - но я не мог получить дальше, чем сообщение WM_PARENTNOTIFY ... После тщательного прочтения MSDN я обнаружил, что некоторая информация содержится в высоком слове wParam, а другая - в низком. Итак, я должен был написать это: if(wParam==(WM_CREATE | (POPUP_COMMAND<<16))){

Как сделать управление глобальным? огромные заявления переключателя? 12 и 14 параметров функции вызовов? Битовые сдвиги для простых уведомлений? Я до сих пор не могу даже понять, как сделать так, чтобы появилось больше одного окна (окна окна, а не окна управления) - это больно ...

Пожалуйста, скажите мне, что есть лучший способ!

Как сделать, кстати, более одного окна? Если я просто зарегистрирую два класса или CreateWindowEx в одном классе дважды (для двух дескрипторов), появится только первый. Я попытался немного поиграть с параметром dwStyle, но безрезультатно. Кто-нибудь?

Ответы [ 9 ]

8 голосов
/ 30 мая 2009

Выступая в качестве бывшего инструктора по программированию на C Windows, я могу с уверенностью сказать, что нет простого способа создать графический интерфейс с использованием C - язык не очень подходит для этой задачи. Почти все остальное было бы лучшим выбором - мой любимый инструмент для разработки GUI - Delphi.

6 голосов
/ 30 мая 2009

Я добавлю свое традиционное нестандартное предложение: добавьте Lua в свое приложение и постройте графический интерфейс с комбинацией Lua и подходящего модуля инструментария. Один хороший выбор - IUP , а другой - wxWidgets . Оба имеют приличное качество привязок Lua. Более того, сама Lua вместе с wxLua и IUP может быть установлена ​​в одной установке вместе с кучей других полезных модулей Lua из проекта Lua для Windows .

Lua легко интегрируется с кодом C, так как он был разработан для этой цели с самого начала.

Также легко использовать Lua в качестве связующего звена, связывающего приложение, с основными функциями, реализованными в C, или в качестве интерфейсов для собственных вызовов API.

Lua также поддерживается SWIG на случай, если у вас есть обширная библиотека для адаптации.

Конечно, вы могли бы просто использовать wxWidgets или IUP непосредственно из C, поскольку у них обоих есть вызываемые API C, но управляемые событиями GUI часто полны придирчивых маленьких служебных функций обратного вызова, с которыми легко иметь дело в язык сценариев.

Другой инструментарий, который следует рассмотреть, - это Tk , который чаще всего встречается в сочетании с языком сценариев Tcl . Tcl также разрабатывался с учетом встраивания в более крупное приложение, хотя и превратился из него в основной сценарий использования. Tk был связан с множеством других языков, включая Perl.

6 голосов
/ 30 мая 2009

Win32 + C - это очень низкоуровневый подход, который имеет свои преимущества и недостатки. Тем не менее, есть способы сделать вещи проще.

Во-первых, что касается сдвигов битов, существует несколько макросов для работы с WPARAM и LPARAMs . Вы, вероятно, не должны писать битовые сдвиги, на самом деле, потому что размер WPARAM и LPARAM изменился за годы , и вы можете создать будущую ошибку.

Во-вторых, что касается гигантского оператора switch в вашей функции WindowProc, хотя он будет там, есть способ сделать его немного более управляемым. #include <windowsx.h>, чтобы получить целую кучу полезных макросов, особенно HANDLE_MSG. Вместо необходимости писать

LRESULT CALLBACK MyWindowProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)    {
    switch(Message) {
    case WM_COMMAND:
        ...
    }
}

Вместо этого вы можете написать:

void MyOnCommand(HWND hwnd, int controlID, HWND hwndCtl, UINT codeNotify);
LRESULT CALLBACK MyWindowProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)    {
    switch(Message) {
    HANDLE_MSG(hwnd, WM_COMMAND, MyOnCommand);
    }
}

и макрос автоматически преобразует и разделяет все различные параметры для этого типа сообщения в переменные с соответствующими именами и типами. Просмотрите windowsx.h, чтобы увидеть обработанные сообщения и необходимые им прототипы функций. Не все разные сообщения обрабатываются, но довольно много.

Что касается одновременного использования нескольких окон, то ничто не должно мешать вам вызывать CreateWindow или его родственников несколько раз. Хотя у вас есть только один HINSTANCE (предоставленный вам в WinMain), вы можете иметь столько HWND, сколько пожелаете.

Вы можете найти скретч-программу Раймонда Чена полезной, поскольку она должна дать вам достойный скелет для начала. Вы также можете подумать о том, чтобы заставить ваше приложение использовать диалоговое окно вместо просто окна; вы получаете кучу вещей бесплатно, и вы можете использовать редактор ресурсов для оформления окна и всех его элементов управления. Visual C ++ Standard и выше включают редактор ресурсов, а также есть несколько бесплатных: XN Resource Editor , кажется, популярный редактор с открытым исходным кодом, и я уверен, что вы можете найти больше на Google. Все они создают сценарий ресурсов, и у вас должен быть компилятор ресурсов в вашей цепочке инструментов: rc.exe для Visual Studio (включая Express Edition или доступный как часть SDK) или windres как часть GNU BinUtils в cygwin или mingw.

4 голосов
/ 30 мая 2009

Я никогда не сталкивался с проблемой написания материалов для Win32 на чистом C, я думаю, что это намного чище, чем альтернативы, которые я пробовал (MFC, WTL, QT и некоторые другие). Несколько простых указателей:

  • Что касается параметров старшего и младшего слова, есть хорошие макросы, чтобы справиться с этим для вас - хотя имена ускользают от меня прямо сейчас.

  • Вы можете работать довольно хорошим объектно-ориентированным способом, выделив структуру «application» и сохранив ее адрес с помощью SetWindowLong (), которая решает проблему наличия глобальных дескрипторов.

  • Вы можете создать довольно простое отображение из указателя функции WM_MESSAGE ->, чтобы упростить возможность перенаправления длинного переключателя в процессах вашего окна, или просто преобразовать его в более простые функции, чтобы получить лучший обзор.

Итак, в общем, можно писать хорошие и чистые вещи, но это сложно. То же самое касается любого другого метода, единственное, что отличается, это значения «возможный» и «сложный»:)

3 голосов
/ 30 мая 2009

GUI в идеале обрабатываются более абстрактными языками, чем C, в противном случае существует много избыточного стандартного кода, в этом смысле я бы посоветовал вам рассмотреть возможность встраивания интерпретатора языка сценариев в ваше приложение C, так что GUI в основном определяется скрипты, а ядро ​​вашего приложения написано на C.

Это также будет иметь преимущество в том, что ваше приложение будет более настраиваемым и более гибким без необходимости перекомпиляции.

Вы захотите взглянуть на облегченные скриптовые движки, написанные на ANSI C и предоставляющие привязки к библиотекам GUI, таким как QT, GTK, wxWindows и т. Д.

Возможно, вы захотите проверить Lua или носовой , оба из которых довольно легки и обеспечивают привязки для библиотек GUI.

В некоторых примерах использования вы можете посмотреть на следующие снимки экрана двух приложений с графическим интерфейсом, которые в основном основаны на носовой привязке и привязках GTK:

3 голосов
/ 30 мая 2009

Есть лучший способ. Используйте Qt. Это для C ++, но C ++ лучше подходит для GUI, потому что его объектно-ориентированная модель очень хорошо подходит для домена. Сам Qt - это отличная библиотека удивительной глубины и ширины, хорошо поддерживаемая и разработанная, лицензированная с LGPL и интересная в использовании. Он поставляется с полным графическим дизайнером, который может помочь вам быстро создавать графические диалоги.

Если вы настаиваете на C и родном Win32, есть и способ. Купите книгу Petzold Programming Windows - это очень хорошо. Прочитав первые несколько глав, вы сможете относительно легко создавать интересные графические интерфейсы на C. Потребуется гораздо больше кода и усилий, чем с Qt, но положительным моментом является то, что вы получите крошечные и быстрые исполняемые файлы без внешних зависимостей.

2 голосов
/ 30 мая 2009

Если вы хотите сделать это на C, вам определенно нужна программа Чарльза Петцольда для программирования Windows.

1 голос
/ 30 мая 2009

Просто чтобы дать вам представление о том, как С сравнивается с другими языками, когда дело доходит до приложений Win UI: Некоторое время назад мне просто простое приложение MDI с несколькими окнами и несколькими классами для визуализации медицинских данных 17 тысяч строк кода в C . Я переписал это в Delphi пару лет спустя, и это заняло всего 5k LOCs .

0 голосов
/ 30 мая 2009

Используя GTK + , вы можете использовать Glade для создания пользовательского интерфейса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...