Re: Edit в дочернем окне неактивен.
От: kero Россия  
Дата: 18.08.10 14:21
Оценка: 35 (2)
Здравствуйте, Deviant.Developer, Вы писали:

DD>Здравствуйте, уважаемые форумчане. Мне очень нужна Ваша помощь.

DD>Учусь писать GUI на Visual C++.
[...]
DD>Вот такой код я набросал.
DD>Что не получается: Edit в дочернем окне не активен и туда не вводится информация.
DD>Если его родительским окном назначить основное, то всё ОК.
DD>Вопросы:
DD>Правильная ли логика и структура программы вообще?
DD>Почему эдит неактивен и как это исправить?
DD>Правильно ли, что дочернее окно и его элементы я создаю в WinMain или лучше запихнуть всё это в обработчик WM_CREATE основного окна? И почему лучше?
DD>Ну и просто покритикуйте код, я ещё только учусь, мог допустить совершенно тупые ошибки именно в логике.
DD>Очень надеюсь на дискуссию с Вами, спасибо.

Вы начали свой путь не с того конца.
На самом деле на данном этапе Вам не "помощь форумчан" и тем более "дискуссия" нужна, а изучение к.н. тутора по WIN API: "Простое окно", "Дочерние окна", "Диалоговое окно как основное" и пр. Т.е. не методом тыка вслепую, а взять работающий пример из тутора, и уже от него отталкиваться, модифицируя его код в разных направлениях, темы тутора их подскажут. Поверьте, так куда быстрее. (Я бы посоветовал начать с "Win32 API Tutorial" от Iczelion-а: во-первых — освоетесь на раз-два, а во-вторых — у самого Iczelion-а немало поучительных ошибок, которые, возможно, специально вкраплены в текст тутора в учебных целях, типа "Внимание, ввожу неисправность" ).

А то, что тем не менее на Ваш код тут отвечают, просто показывает, насколько интеллигентен наш форум
По всему, пашиным хозяевам позарез нужна война в Европе
(уверены — к ним не залетит, в предыдущих двух не залетало жеж)
Автор: kero
Дата: 21.07.14
Re[2]: Edit в дочернем окне неактивен.
От: okman Беларусь https://searchinform.ru/
Дата: 17.08.10 22:08
Оценка: 3 (1)
Приветствую всех.

Для построения таких отношений, как в коде топикстартера, нужно прибегать к архитектуре MDI.
В MFC, кстати, разделение на фреймовые и клиентские окна тоже не зря сделано — фреймовое окно
управляет рамкой и системным меню, а за клиентскую область отвечает другая сущность.

Вот код, где делается попытка решить проблему чисто на диалогах:

#include <windows.h>
#include "resource.h"



HINSTANCE g_hInstance;



/**********************************************

Процедура дочернего окна.

**********************************************/

INT_PTR _stdcall ChildWindowProc(HWND hWnd,
                                 UINT uMsg,
                                 WPARAM wParam,
                                 LPARAM lParam)
{
    switch (uMsg)
    {
    case WM_INITDIALOG:
        // Создается edit control.
        CreateWindowExW(NULL,
            L"Edit",
            NULL,
            WS_CHILD | WS_VISIBLE,
            ...,
            ...,
            ...,
            ...,
            hWnd,
            NULL,
            g_hInstance,
            NULL);
        break;
    }

    return 0;
}



/**********************************************

Процедура главного окна.

**********************************************/

INT_PTR _stdcall MainWindowProc(HWND hWnd,
                                UINT uMsg,
                                WPARAM wParam,
                                LPARAM lParam)
{
    switch (uMsg)
    {
    case WM_INITDIALOG:
        // Создается дочернее немодальное окно (со стилем WS_CHILD).
        CreateDialogParamW(g_hInstance,
            MAKEINTRESOURCEW(IDD_CHILDFORM),
            hWnd,
            ChildWindowProc,
            0);

        break;
    }

    return 0;
}



/**********************************************

Точка входа в программу.

**********************************************/

int _stdcall WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int)
{
    g_hInstance = hInstance;

    // Создается главное окно.
    DialogBoxParamW(hInstance,
        MAKEINTRESOURCEW(IDD_MAINFORM),
        NULL,
        MainWindowProc,
        0);

    return 0;
}


Тут edit, правда, откликается, но все равно само дочернее окно как бы не в фокусе и
не работает выделение текста мышкой или по Ctrl + A.
Re[3]: Edit в дочернем окне неактивен.
От: Кодт Россия  
Дата: 18.08.10 06:58
Оценка: 3 (1)
Здравствуйте, Deviant.Developer, Вы писали:

DD>И всё же, WS_CAPTION отвечает за заголовок окна, если убрать, это будет тупо рамочка, что меня не совсем устраивает. Так что в ближайшее время буду думать над вариантами.


А что, если взять готовый контрол?
Например, BUTTON со стилем BS_GROUPBOX — рамочка с заголовком.

DD>Ну и, конечно, остается вопрос: как взаимосвязан этот флаг и "активность" Edit'а?

DD>Убираешь флаг WS_CAPTION и получаешь рамку на форме и Edit в который можно вводить символы. Добавляешь флаг и получаешь отдельное окошко, но при этом Edit "умирает". В чем фокус ? Предстоит разобраться.

Прими как данность, что у дочерних окон ограниченные возможности по рисованию неклиентских элементов.
Было бы внезапно, например, ожидать там WS_SYSMENU или WS_MINIMIZEBOX.
Нет, конечно же, ты можешь написать собственное окно, которое реализует все WM_NCPAINT и т.п. так, как тебе это нужно...
но похоже, что в обычной жизни у дочернего окна наступило умопомрачение.

Впрочем, можно предположить, что это умопомрачение кратковременно: во время инициализации окошко задисаблило само себя (вместе с содержимым — эдитом).
Попробуй проверить — прочитать IsWindowEnabled(LogonWnd), и включить EnableWindow(LogonWnd,TRUE).
Вдруг поможет?
Перекуём баги на фичи!
Re[2]: Edit в дочернем окне неактивен.
От: Jolly Roger  
Дата: 18.08.10 10:11
Оценка: 3 (1)
Здравствуйте, Deviant.Developer, Вы писали:

DD>К слову, если использовать popup окно, то получается то что я хочу — и edit активен и всё в отдельном окошечке. Это нормальный вариант для использования в программе и чем он лучше\хуже диалоговых окон?


Да ничем не хуже, просто собирать такие окошки по кусочкам в рантайм — путь для очень уж трудолюбивых людей

DD>Просто это интересно — писать интерфейс на WinAPI, я привык работать с VCL, MFC, а вот так чтобы вручную писать не пробовал, так что теперь идет тяжелый и забавный процесс обучения. Короче, я совсем deviant


Ну дык, DialogBox или там CreateDialogParam — самый что ни на есть WinApi
"Нормальные герои всегда идут в обход!"
Re[2]: Edit в дочернем окне неактивен.
От: Кодт Россия  
Дата: 18.08.10 13:26
Оценка: 3 (1)
Здравствуйте, Deviant.Developer, Вы писали:

К>>Попробуй проверить — прочитать IsWindowEnabled(LogonWnd), и включить EnableWindow(LogonWnd,TRUE).

К>>Вдруг поможет?
DD>Это первое что мне пришло в голову. Возвращает что окно активно

Только, чтобы в терминах не путаться. Активно — это GetActiveWindow, текущее popup/overlapped окно системы. А IsWindowEnabled — это "включено" (или какой там официальный перевод?)

Я немножко поэкспериментировал с твоим кодом.
Если после создания сказать эдитбоксу SetFocus, то оно получает этот самый фокус. При том, что LogonWindow по-прежнему неактивно (имеет бледную рамку).
Перекуём баги на фичи!
Re: Edit в дочернем окне неактивен.
От: okman Беларусь https://searchinform.ru/
Дата: 17.08.10 14:16
Оценка: 2 (1)
Здравствуйте, Deviant.Developer.

По-моему, нет большого смысла регистрировать новый класс окна ради такой маленькой задачи, как ввод пароля.
Лучше в обработчике WM_CREATE главного окна вызвать DialogBoxParam (или CreateDialogParam для немодального диалога).

На счет edit-а не знаю, возможно, указаны неправильные стили окна.
В любом случае, дочерние окна не предназначены для пользовательского ввода.

А код нормальный, только немного "сплюснутый" (воздуха по вертикали не хватает).
Блоки case лучше оформлять как-то по-другому, чтобы не забыть про break.
И еще хорошо бы придерживаться согласованного стиля именования — если одно окно называете hMainWnd,
то и второе должно называться hLogonWnd, а не LogonWnd.
Re: Edit в дочернем окне неактивен.
От: Jolly Roger  
Дата: 18.08.10 07:57
Оценка: 2 (1)
Здравствуйте, Deviant.Developer, Вы писали:

DD>Здравствуйте, уважаемые форумчане. Мне очень нужна Ваша помощь.

DD>Учусь писать GUI на Visual C++.

А где в приведённом коде используется C++?

А зачем Вам делать его чилдом? Почему-бы не использовать обычный модальный диалог? Нарисуйте его в ресурсах и показывайте DialogBox. Это куда удобнее, да и можно подготовить несколько диалогов для разных языков.
"Нормальные герои всегда идут в обход!"
Edit в дочернем окне неактивен.
От: Deviant.Developer  
Дата: 17.08.10 11:26
Оценка:
Здравствуйте, уважаемые форумчане. Мне очень нужна Ваша помощь.
Учусь писать GUI на Visual C++.
Логика моей задачи такая: появляется основное окно и тут же появляется диалоговое окно, в котором пользователю предлагается ввести данные.

Что делаю:


#include <windows.h>
//----------------------------------------------------------------------------------
LRESULT CALLBACK MainframeProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
        case WM_DESTROY: {PostQuitMessage(0); return 0;}
    }
    return DefWindowProc(hwnd, msg, wParam, lParam);
}
//----------------------------------------------------------------------------------
LRESULT CALLBACK LogonframeProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
        case WM_DESTROY: {CloseWindow(hwnd); return 0;}
    }
    return DefWindowProc(hwnd, msg, wParam, lParam);
}
//----------------------------------------------------------------------------------
BOOL RegClass(WNDPROC Proc, LPCTSTR szName, HINSTANCE hInstance)
{
    WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_HREDRAW | CS_VREDRAW, Proc, 0, 0, 
                  hInstance, LoadIcon(NULL, IDI_APPLICATION), LoadCursor(NULL, IDC_ARROW), 
                  (HBRUSH)GetStockObject(GRAY_BRUSH), 0, szName, LoadIcon(NULL, IDI_APPLICATION)};
    return (RegisterClassEx(&wc) != 0);
}
//----------------------------------------------------------------------------------
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    
    RegClass(MainframeProc, L"Mainframe", hInstance);
    HWND hMainWnd=CreateWindow(L"Mainframe", L"клиент", WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, (HWND)NULL, (HMENU)NULL, (HINSTANCE)hInstance, NULL);
    ShowWindow(hMainWnd, nCmdShow);
    UpdateWindow(hMainWnd);
    //---создаем дочернее окно для ввода логина
        RegClass(LogonframeProc, L"LogonFrame", hInstance);
        HWND LogonWnd=CreateWindowEx(0,L"LogonFrame",L"авторизация",
                                WS_CHILD | WS_VISIBLE | WS_BORDER | WS_CAPTION | WS_SIZEBOX | WS_MINIMIZEBOX |WS_SYSMENU | WS_MAXIMIZEBOX, 
                                0, 0, 200,200,hMainWnd,NULL,hInstance,NULL);
        //--создаем на окне авторизации элемент ввода
        CreateWindowEx(WS_EX_CLIENTEDGE,L"EDIT",L"",WS_CHILD|WS_VISIBLE|ES_PASSWORD,
                    10,50,125,25,LogonWnd,(HMENU)4953495,NULL,NULL);
    //---
    MSG msg;
    while(GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return (int)msg.wParam;
}


Вот такой код я набросал.
Что не получается: Edit в дочернем окне не активен и туда не вводится информация.
Если его родительским окном назначить основное, то всё ОК.

Вопросы:
Правильная ли логика и структура программы вообще?
Почему эдит неактивен и как это исправить?
Правильно ли, что дочернее окно и его элементы я создаю в WinMain или лучше запихнуть всё это в обработчик WM_CREATE основного окна? И почему лучше?
Ну и просто покритикуйте код, я ещё только учусь, мог допустить совершенно тупые ошибки именно в логике.

Очень надеюсь на дискуссию с Вами, спасибо.
Re[2]: Edit в дочернем окне неактивен.
От: Deviant.Developer  
Дата: 17.08.10 14:59
Оценка:
okman, спасибо за ответ. Тогда посмотрю и реализую предложенный Вами вариант с DialogBoxParam.

O>В любом случае, дочерние окна не предназначены для пользовательского ввода.

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

Ну и проблема с неактивным Edit остается актуальной. Чуть позже ещё раз свежим взглядом посмотрю на код и подумаю, где могут быть грабли.
Re[2]: Edit в дочернем окне неактивен.
От: kero Россия  
Дата: 17.08.10 15:03
Оценка:
Здравствуйте, okman, Вы писали:

O>В любом случае, дочерние окна не предназначены для пользовательского ввода.


А какие предназначены ?
По всему, пашиным хозяевам позарез нужна война в Европе
(уверены — к ним не залетит, в предыдущих двух не залетало жеж)
Автор: kero
Дата: 21.07.14
Re[2]: Edit в дочернем окне неактивен.
От: Deviant.Developer  
Дата: 17.08.10 17:58
Оценка:
Здравствуйте, okman, Вы писали:
O>На счет edit-а не знаю, возможно, указаны неправильные стили окна.
И действительно, дело оказалось именно в этом. Чтобы Edit "заработал", достаточно убрать флаг WS_CAPTION при создании дочернего окна.
Собственно, разобрался(после футбола голова как никогда свежая ) ещё раз спасибо.

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

Ну и, конечно, остается вопрос: как взаимосвязан этот флаг и "активность" Edit'а?
Убираешь флаг WS_CAPTION и получаешь рамку на форме и Edit в который можно вводить символы. Добавляешь флаг и получаешь отдельное окошко, но при этом Edit "умирает". В чем фокус ? Предстоит разобраться.
Re: Edit в дочернем окне неактивен.
От: Deviant.Developer  
Дата: 18.08.10 09:44
Оценка:
Спасибо за ответы и советы, они мне помогают.

Здравствуйте, Кодт, Вы писали:
К>Впрочем, можно предположить, что это умопомрачение кратковременно: во время инициализации окошко задисаблило само себя (вместе с содержимым — эдитом).
К>Попробуй проверить — прочитать IsWindowEnabled(LogonWnd), и включить EnableWindow(LogonWnd,TRUE).
К>Вдруг поможет?
Это первое что мне пришло в голову. Возвращает что окно активно

Здравствуйте, Jolly Roger, Вы писали:
JR>А где в приведённом коде используется C++?
Нигде, изначально цель была попрактиковаться в написании интерфейса на WinAPI. Просто использую эту IDE.
JR>А зачем Вам делать его чилдом? Почему-бы не использовать обычный модальный диалог? Нарисуйте его в ресурсах и показывайте DialogBox. Это куда удобнее, да и можно подготовить несколько диалогов для разных языков.
Скорее всего так и сделаю. Покурю приведенный тут пример и разберусь (спасибо, okman).

К слову, если использовать popup окно, то получается то что я хочу — и edit активен и всё в отдельном окошечке. Это нормальный вариант для использования в программе и чем он лучше\хуже диалоговых окон?

Просто это интересно — писать интерфейс на WinAPI, я привык работать с VCL, MFC, а вот так чтобы вручную писать не пробовал, так что теперь идет тяжелый и забавный процесс обучения. Короче, я совсем deviant
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.