Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Низкоуровневое программирование > Win Api
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 28.05.2012, 14:38   #1
8Observer8
Старожил
 
Аватар для 8Observer8
 
Регистрация: 02.01.2011
Сообщений: 3,323
По умолчанию Переписываем уроки Iczelion'а о Win32 API на C

Все кто заинтересуется этой темой выкладывайте здесь примеры из уроков Iczelion'а, переписанные на С.

Уроки Iczelion'а --> http://wasm.ru/publist.php?list=1

Урок 9. Дочерние окна --> http://wasm.ru/article.php?article=1001009

(29.05.2012) Внимание! Исправил код в соответствии с сообщением-замечанием №3 от netrino!

main.c
Код:
#include <windows.h>
#include <tchar.h>

LRESULT CALLBACK WindowProc(HWND hwnd,
                            UINT uMsg,
                            WPARAM wParam,
                            LPARAM lParam);

LPCTSTR ClassName = _T("SimpleWinClass");
LPCTSTR AppName = _T("Our First Window");
LPCTSTR MenuName = _T("FirstMenu");

HINSTANCE hInstance;

int WINAPI _tWinMain(HINSTANCE hInst,
                     HINSTANCE hPrevInstance,
                     LPTSTR lpCmdLine,
                     int nCmdShow)
{
    WNDCLASSEX wc;
    MSG msg;
    HWND hwnd;

    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = WindowProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    hInstance = hInst;
    wc.hInstance = hInstance;
    wc.hIcon = LoadIcon((HINSTANCE) NULL, IDI_APPLICATION);
    wc.hCursor = LoadCursor((HINSTANCE) NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH) (COLOR_BTNFACE+1);
    wc.lpszMenuName = MenuName;
    wc.lpszClassName = ClassName;
    wc.hIconSm = LoadIcon((HINSTANCE) NULL, IDI_APPLICATION);

    if (RegisterClassEx(&wc) == 0) {
        MessageBox(NULL, _T("Cannot regiser window class"), _T("Error"), MB_ICONERROR);
        return FALSE;
    }

    hwnd = CreateWindowEx(WS_EX_CLIENTEDGE,
                          ClassName,
                          AppName,
                          WS_OVERLAPPEDWINDOW,
                          CW_USEDEFAULT,
                          CW_USEDEFAULT,
                          300,
                          200,
                          (HWND) NULL,
                          (HMENU) NULL,
                          hInst,
                          NULL);

    if (hwnd == NULL) {
        MessageBox(NULL, _T("Cannot create window"), _T("Error"), MB_ICONERROR);
        return FALSE;
    }

    ShowWindow(hwnd, SW_SHOWDEFAULT);
    UpdateWindow(hwnd);

    while(GetMessage(&msg, NULL, 0, 0) != 0) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return msg.wParam;
}
Продолжение этого кода (из main.c) в следующем сообщении.

Последний раз редактировалось 8Observer8; 29.05.2012 в 12:28.
8Observer8 вне форума Ответить с цитированием
Старый 28.05.2012, 14:40   #2
8Observer8
Старожил
 
Аватар для 8Observer8
 
Регистрация: 02.01.2011
Сообщений: 3,323
По умолчанию

main.c (продолжение)
Код:
#define BSIZE 512
#define ButtonID 1
#define EditID 2
#define IDM_HELLO 1
#define IDM_CLEAR 2
#define IDM_GETTEXT 3
#define IDM_EXIT 4

LPCTSTR ButtonClassName = _T("button");
LPCTSTR ButtonText = _T("My First Button");
LPCTSTR EditClassName = _T("edit");
LPCTSTR TestString = _T("Wow! I'm in an edit box now");

LRESULT CALLBACK WindowProc(HWND hWnd,
                            UINT uMsg,
                            WPARAM wParam,
                            LPARAM lParam)
{
    static HWND hwndEdit;
    static HWND hwndButton;
    TCHAR buffer[BSIZE];

    switch(uMsg) {
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    case WM_CREATE:
        hwndEdit = CreateWindowEx(WS_EX_CLIENTEDGE,
                                  EditClassName,
                                  NULL,
                                  WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT | ES_AUTOHSCROLL,
                                  50, 35,
                                  200, 25,
                                  hWnd,
                                  (HMENU) NULL,
                                  hInstance,
                                  NULL);
        SetFocus(hwndEdit);

        hwndButton = CreateWindowEx(0,
                                    ButtonClassName,
                                    ButtonText,
                                    WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
                                    75, 70,
                                    140, 25,
                                    hWnd,
                                    (HMENU)ButtonID,
                                    hInstance,
                                    NULL);
        break;
    case WM_COMMAND:
        if (lParam == 0) {
            if (LOWORD(wParam) == IDM_HELLO) {
                SetWindowText(hwndEdit, TestString);
                SendMessage(hwndEdit, WM_KEYDOWN, (WPARAM) VK_END, (LPARAM) NULL);
            }
            else if (LOWORD(wParam) == IDM_CLEAR) {
                SetWindowText(hwndEdit, NULL);
            }
            else if (LOWORD(wParam) == IDM_GETTEXT) {
                GetWindowText(hwndEdit, buffer, BSIZE);
                MessageBox(NULL, buffer, AppName, MB_OK);
            }
            else {
                DestroyWindow(hWnd);
            }
        }
        else {
            if (LOWORD(wParam) == ButtonID) {
                if (HIWORD(wParam) == BN_CLICKED) {
                    SendMessage(hWnd, WM_COMMAND, IDM_GETTEXT, 0);
                }
            }
        }
        break;
    default:
        return DefWindowProc(hWnd, uMsg, wParam, lParam);
    }

    return 0;
}
controls.rc
Код:
#define IDM_HELLO 1
#define IDM_CLEAR 2
#define IDM_GETTEXT 3
#define IDM_EXIT 4

FirstMenu MENU
{
 POPUP "&Test Controls"
        {
         MENUITEM "Say Hello",IDM_HELLO
         MENUITEM "Clear Edit Box",IDM_CLEAR
         MENUITEM "Get Text", IDM_GETTEXT
         MENUITEM SEPARATOR
         MENUITEM "E&xit",IDM_EXIT
        }
}


P.S. Поля в структуре WNDCLASSEX я инициализировал в том порядке в котором они представлены в документации MSDN.

Последний раз редактировалось 8Observer8; 29.05.2012 в 12:28.
8Observer8 вне форума Ответить с цитированием
Старый 28.05.2012, 21:19   #3
netrino
Участник клуба
 
Аватар для netrino
 
Регистрация: 15.07.2008
Сообщений: 1,933
По умолчанию

Что же, успехов Вам в начинаниях, наверняка кому-то это пригодится. Сделаю небольшое предостережение, если используете LPCTSTR как тип переменной, то не забывайте оборачивать литерал строки в макровыражение _T
Код:
LPCTSTR ButtonClassName = _T("button");
Иначе, если в настройках проекта стоит кодировка Unicode, то программа не скомпилируется. То же самое касается всех char и char* заменить на TCHAR и LPTSTR. Также, совсем для верности, заменить WinMain на _tWinMain.
netrino вне форума Ответить с цитированием
Старый 28.05.2012, 21:28   #4
8Observer8
Старожил
 
Аватар для 8Observer8
 
Регистрация: 02.01.2011
Сообщений: 3,323
По умолчанию

Конечно пригодится! К тому же под контролем старших товарищей вылезут недочёты и упущения! netrino, благодарю! А что если ставить L"hello"?
8Observer8 вне форума Ответить с цитированием
Старый 28.05.2012, 22:10   #5
netrino
Участник клуба
 
Аватар для netrino
 
Регистрация: 15.07.2008
Сообщений: 1,933
По умолчанию

Цитата:
Сообщение от 8Observer8 Посмотреть сообщение
Конечно пригодится! К тому же под контролем старших товарищей вылезут недочёты и упущения! netrino, благодарю! А что если ставить L"hello"?
Просто "hello" соответствует типу const char * (LPCSTR), L"hello" соответствует const wchar_t * (LPCWSTR). _T("hello"), в зависимости от настроек, будет раскрыт в "hello" или L"hello"
Код:
#ifdef _UNICODE
# define _T(str) L##str
#else
# define _T(str) str
#endif
Следовательно, подставлять L"hello" тоже не стоит, во всяком случае, если используется LPCTSTR.
netrino вне форума Ответить с цитированием
Старый 28.05.2012, 22:42   #6
8Observer8
Старожил
 
Аватар для 8Observer8
 
Регистрация: 02.01.2011
Сообщений: 3,323
По умолчанию

Теперь стало понятно! Спасибо огромное! Ваш развёрнутый ответ для меня очень важен! Пора было мне с этими кодировками разобраться, а то я слишком часто на этом спотыкался.

Последний раз редактировалось 8Observer8; 28.05.2012 в 23:02.
8Observer8 вне форума Ответить с цитированием
Старый 29.05.2012, 12:16   #7
8Observer8
Старожил
 
Аватар для 8Observer8
 
Регистрация: 02.01.2011
Сообщений: 3,323
По умолчанию

Урок 10. Диалоговое окно как основное (первый пример) --> http://wasm.ru/article.php?article=1001010

main.c
Код:
#include <windows.h>
#include <tchar.h>

#define IDC_EDIT 3000

LRESULT CALLBACK WindowProc(HWND hwnd,
                            UINT uMsg,
                            WPARAM wParam,
                            LPARAM lParam);

LPCTSTR ClassName = _T("DLGCLASS");
LPCTSTR MenuName = _T("MyMenu");
LPCTSTR DlgName = _T("MyDialog");

HINSTANCE hInstance;

int WINAPI _tWinMain(HINSTANCE hInst,
                     HINSTANCE hPrevInstance,
                     LPTSTR lpCmdLine,
                     int nCmdShow)
{
    WNDCLASSEX wc;
    MSG msg;
    HWND hDlg;

    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = WindowProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = DLGWINDOWEXTRA;
    hInstance = hInst;
    wc.hInstance = hInstance;
    wc.hIcon = LoadIcon((HINSTANCE) NULL, IDI_APPLICATION);
    wc.hCursor = LoadCursor((HINSTANCE) NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH) (COLOR_BTNFACE+1);
    wc.lpszMenuName = MenuName;
    wc.lpszClassName = ClassName;
    wc.hIconSm = LoadIcon((HINSTANCE) NULL, IDI_APPLICATION);

    if (RegisterClassEx(&wc) == 0) {
        MessageBox(NULL, _T("Cannot regiser a window class"), _T("Error"), MB_ICONERROR);
        return FALSE;
    }

    hDlg = CreateDialogParam(hInstance, DlgName, NULL, NULL, (LPARAM) NULL);

    if (hDlg == NULL) {
        MessageBox(NULL, _T("Cannot create a dialog window"), _T("Error"), MB_ICONERROR);
        return FALSE;
    }

    SetFocus(GetDlgItem(hDlg, IDC_EDIT));

    ShowWindow(hDlg, SW_SHOWNORMAL);
    UpdateWindow(hDlg);

    while(GetMessage(&msg, NULL, 0, 0) != 0) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return msg.wParam;
}
Продолжение этого кода (из main.c) в следующем сообщении.

Последний раз редактировалось 8Observer8; 29.05.2012 в 12:22.
8Observer8 вне форума Ответить с цитированием
Старый 29.05.2012, 12:21   #8
8Observer8
Старожил
 
Аватар для 8Observer8
 
Регистрация: 02.01.2011
Сообщений: 3,323
По умолчанию

main.c (продолжение)
Код:
#define BSIZE 512
#define IDC_BUTTON 3001
#define IDC_EXIT 3002
#define IDM_GETTEXT 32000
#define IDM_CLEAR 32001
#define IDM_EXIT 32002

LPCTSTR AppName = _T("Our First Dialog Box");
LPCTSTR TestString = _T("Wow! I'm in an edit box now");

LRESULT CALLBACK WindowProc(HWND hWnd,
                            UINT uMsg,
                            WPARAM wParam,
                            LPARAM lParam)
{
    static HWND hwndEdit;
    static HWND hwndButton;
    TCHAR buffer[BSIZE];

    switch(uMsg) {
    case WM_CREATE:
        SetDlgItemText(hWnd, IDC_EDIT, AppName);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    case WM_COMMAND:
        if (lParam == 0) {
            if (LOWORD(wParam) == IDM_GETTEXT) {
                GetDlgItemText(hWnd, IDC_EDIT, buffer, BSIZE);
                MessageBox(NULL, buffer, AppName, MB_OK);
            }
            else if (LOWORD(wParam) == IDM_CLEAR) {
                SetDlgItemText(hWnd, IDC_EDIT, NULL);
            }
            else {
                DestroyWindow(hWnd);
            }
        }
        else {
            if (HIWORD(wParam) == BN_CLICKED) {
                SetDlgItemText(hWnd, IDC_EDIT, TestString);
            }
            else if (HIWORD(wParam) == IDC_EXIT) {
                SendMessage(hWnd, WM_COMMAND, IDM_EXIT, 0);
            }
        }
        break;
    default:
        return DefWindowProc(hWnd, uMsg, wParam, lParam);
    }

    return 0;
}
dialog.rc
Код:
#define DS_CENTER             0x0800L
#define WS_CAPTION            0x00C00000L
#define WS_MINIMIZEBOX        0x00020000L
#define WS_SYSMENU            0x00080000L
#define WS_VISIBLE            0x10000000L
#define WS_OVERLAPPED         0x00000000L
#define DS_MODALFRAME         0x80L
#define DS_3DLOOK             0x0004L
#define ES_AUTOHSCROLL        0x0080L
#define ES_LEFT               0x0000L
#define WS_TABSTOP            0x00010000L

#define IDC_EDIT              3000
#define IDC_BUTTON            3001
#define IDC_EXIT              3002

#define IDM_GETTEXT           32000
#define IDM_CLEAR             32001
#define IDM_EXIT              32003

MyDialog DIALOG 10, 10, 205, 60
STYLE 0x0004 | DS_CENTER | WS_CAPTION | WS_MINIMIZEBOX |
WS_SYSMENU | WS_VISIBLE | WS_OVERLAPPED | DS_MODALFRAME | DS_3DLOOK
CAPTION "Our First Dialog Box"
CLASS "DLGCLASS"
BEGIN
    EDITTEXT         IDC_EDIT, 15, 17, 111, 13, ES_AUTOHSCROLL | ES_LEFT | WS_TABSTOP
    DEFPUSHBUTTON   "Say Hello", IDC_BUTTON, 141, 10, 52, 13
    PUSHBUTTON      "E&xit", IDC_EXIT, 141, 26, 52, 13
END

MyMenu  MENU
BEGIN
    POPUP "Test Controls"
    BEGIN
        MENUITEM "Get Text", IDM_GETTEXT
        MENUITEM "Clear Text", IDM_CLEAR
        MENUITEM "", , 0x0800 /*MFT_SEPARATOR*/
        MENUITEM "E&xit", IDM_EXIT
    END
END


P.S. Вместо того, чтобы подключать файл resource.h - я скопировал из него все объявления констант в файл dialog.rc.

Последний раз редактировалось 8Observer8; 29.05.2012 в 12:31.
8Observer8 вне форума Ответить с цитированием
Старый 30.05.2012, 04:46   #9
8Observer8
Старожил
 
Аватар для 8Observer8
 
Регистрация: 02.01.2011
Сообщений: 3,323
По умолчанию

Урок 10. Диалоговое окно как основное (второй пример) --> http://wasm.ru/article.php?article=1001010

main.c
Код:
#include <windows.h>
#include <tchar.h>

#define BSIZE          512
#define IDC_EDIT       3000
#define IDC_BUTTON     3001
#define IDC_EXIT       3002
#define IDM_GETTEXT    32000
#define IDM_CLEAR      32001
#define IDM_EXIT       32002
#define MyDialog       100

INT_PTR CALLBACK DialogProc(HWND hwndDlg,
                            UINT uMsg,
                            WPARAM wParam,
                            LPARAM lParam);

LPCTSTR DlgName = MAKEINTRESOURCE(MyDialog);
LPCTSTR AppName = _T("Our Second Dialog Box");
LPCTSTR TestString = _T("Wow! I'm in an edit box now");

int WINAPI _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR lpCmdLine,
                     int nCmdShow)
{
    DialogBoxParam(hInstance, DlgName, NULL, DialogProc, (LPARAM) NULL);

    return TRUE;
}

INT_PTR CALLBACK DialogProc(HWND hWnd,
                            UINT uMsg,
                            WPARAM wParam,
                            LPARAM lParam)
{
    TCHAR buffer[BSIZE];

    switch(uMsg) {
    case WM_INITDIALOG:
        SetFocus(GetDlgItem(hWnd, IDC_EDIT));
        break;
    case WM_CLOSE:
        SendMessage(hWnd, WM_COMMAND, IDM_EXIT, 0);
        break;
    case WM_COMMAND:
        if (lParam == 0) {
            if (LOWORD(wParam) == IDM_GETTEXT) {
                GetDlgItemText(hWnd, IDC_EDIT, buffer, BSIZE);
                MessageBox(NULL, buffer, AppName, MB_OK);
            }
            else if (LOWORD(wParam) == IDM_CLEAR) {
                SetDlgItemText(hWnd, IDC_EDIT, NULL);
            }
            else if (LOWORD(wParam) == IDM_EXIT) {
                EndDialog(hWnd, 0);
            }
        }
        else {
            if (HIWORD(wParam) == BN_CLICKED) {
                if (LOWORD(wParam) == IDC_BUTTON) {
                    SetDlgItemText(hWnd, IDC_EDIT, TestString);
                }
                else if (LOWORD(wParam) == IDC_EXIT) {
                    SendMessage(hWnd, WM_COMMAND, IDM_EXIT, 0);
                }
            }
        }
        break;
    default:
        return FALSE;
    }

    return TRUE;
}
dialog.rc
Код:
#define DS_CENTER             0x0800L
#define WS_CAPTION            0x00C00000L
#define WS_MINIMIZEBOX        0x00020000L
#define WS_SYSMENU            0x00080000L
#define WS_VISIBLE            0x10000000L
#define WS_OVERLAPPED         0x00000000L
#define DS_MODALFRAME         0x80L
#define DS_3DLOOK             0x0004L
#define ES_AUTOHSCROLL        0x0080L
#define ES_LEFT               0x0000L

#define IDR_MENU1             3003
#define IDC_EDIT              3000
#define IDC_BUTTON            3001
#define IDC_EXIT              3002

#define IDM_GETTEXT           32000
#define IDM_CLEAR             32001
#define IDM_EXIT              32002
#define MyDialog              100

MyDialog DIALOG 10, 10, 205, 60
STYLE 0x0004 | DS_CENTER | WS_CAPTION | WS_MINIMIZEBOX |
WS_SYSMENU | WS_VISIBLE | WS_OVERLAPPED | DS_MODALFRAME | DS_3DLOOK
CAPTION "Our Second Dialog Box"
MENU IDR_MENU1
BEGIN
    EDITTEXT         IDC_EDIT, 15, 17, 111, 13, ES_AUTOHSCROLL | ES_LEFT
    DEFPUSHBUTTON   "Say Hello", IDC_BUTTON, 141, 10, 52, 13
    PUSHBUTTON      "E&xit", IDC_EXIT, 141, 26, 52, 13
END

IDR_MENU1  MENU
BEGIN
    POPUP "Test Controls"
    BEGIN
        MENUITEM "Get Text", IDM_GETTEXT
        MENUITEM "Clear Text", IDM_CLEAR
        MENUITEM "", , 0x0800 /*MFT_SEPARATOR*/
        MENUITEM "E&xit", IDM_EXIT
    END
END


P.S. Константы из файла resource.h скопированы в файл dialog.rc

P.S.S Была найдена ошибка в данном примере урока Iczelion'а:
- в файлах dialog.asm и dialog.rc значения констант IDM_EXIT были разными. Это приводило к тому, что при нажатии в меню на пункт "Exit" завершение программы не происходило.

Последний раз редактировалось 8Observer8; 30.05.2012 в 04:49.
8Observer8 вне форума Ответить с цитированием
Старый 30.05.2012, 04:47   #10
8Observer8
Старожил
 
Аватар для 8Observer8
 
Регистрация: 02.01.2011
Сообщений: 3,323
По умолчанию

Обнаружил странное поведение в предыдущей программе. Если блоке case WM_COMMAND написать:
Код:
a = LOWORD(wParam);
b = IDC_EXIT;
И поставить точку останова, то перед появлением окна выполнение остановится на нашей точки останова и значения переменных a и b будет соответственно равно: 3000, 3002; wParam = 0x01000bb8. При продолжении выполнения появляется окно. Нажимаем на кнопку Exit - значение переменных: a = 3000, b = 3002, wParam = 0x02000bb8. Опять продолжаем выполнение и получаем: a = 3002, b = 3002, wParam = 0x00000bba. Ещё продолжаем 2 раза (здесь уже понятно). Программа завершается.

Если кто-нибудь найдёт время, то проясните, пожалуйста, этот вопрос! Что происходит?

Последний раз редактировалось 8Observer8; 30.05.2012 в 04:51.
8Observer8 вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Win32 API Tymchuk C++ Builder 0 16.05.2012 21:53
win32 API.Visual Studio 2008.Создание проекта Win32 Aleksandr_Yanov Visual C++ 2 12.09.2010 13:09
Win32 API. VS2008. Как создать приложение win32 в vs2008? Aleksandr_Yanov Visual C++ 4 12.09.2010 00:59
Win32 Api revaldo666 Win Api 10 06.07.2010 00:48
Win32 Api! alexov Общие вопросы C/C++ 7 09.02.2009 22:25