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

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

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

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

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

Ответ
 
Опции темы Поиск в этой теме
Старый 05.05.2012, 21:35   #1
8Observer8
Старожил
 
Аватар для 8Observer8
 
Регистрация: 02.01.2011
Сообщений: 3,323
По умолчанию Ограничение ввода в edit

Приветствую! Следующая программа демонстрационная. Получает два числа из двух Edit'ов и выводит в третий сумму этих чисел. Мне нужно сабклассить Edit'ы для ввода только чисел. Делаю по подобию: http://wasm.ru/article.php?article=1001020. Попытался сабклассить первый Edit. При запуске программы невозможно ввести данные в него (окно Edit'а как-будто зависает). В процедуре EditWndProc в default проваливаемся. Заранее спасибо!

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

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

LPCTSTR szDlgName = MAKEINTRESOURCE(IDD_DIALOG1);

INT_PTR CALLBACK EditWndProc(HWND hEdit,
                            UINT uMsg,
                            WPARAM wParam,
                            LPARAM lParam );

int WINAPI WinMain(HINSTANCE hInstance,
                   HINSTANCE hPrevInstance,
                   LPSTR lpCmdLine,
                   int nCmdShow)
{
    return DialogBoxParam(hInstance, szDlgName, NULL, BasicDialogProc, NULL);
}

#define BSIZE 512
char buf[BSIZE];
int a;
int b;
int result;
long OldWndProc;
HWND hEdit;

INT_PTR CALLBACK BasicDialogProc(HWND hwndDlg,
                            UINT uMsg,
                            WPARAM wParam,
                            LPARAM lParam )
{
    switch (uMsg) {
    case WM_INITDIALOG:
        // инициализируем Edit'ы
        SetDlgItemText(hwndDlg, IDC_EDIT_A, "0");
        SetDlgItemText(hwndDlg, IDC_EDIT_B, "0");
        SetDlgItemText(hwndDlg, IDC_EDIT_RESULT, "0");

        // замещаем адpес оpигинальной пpоцедуpы окна нашим собственным адpесом
        hEdit = GetDlgItem(hwndDlg, IDC_EDIT_A);
        OldWndProc = SetWindowLong(hEdit, GWL_WNDPROC, EditWndProc);
        break;
    case WM_COMMAND:

        // нажатием на кнопку Cancel, закрываем окно
        if (LOWORD(wParam) == IDCANCEL) {
            SendMessage(hwndDlg, WM_CLOSE, 0, 0);

        // нажатием на кнопку Ok, обрабатываем данные
        } else if (LOWORD(wParam) == IDOK) {
            // получаем первое число
            GetDlgItemText(hwndDlg, IDC_EDIT_A, buf, BSIZE);
            a = atoi(buf);
            // получаем второе число
            GetDlgItemText(hwndDlg, IDC_EDIT_B, buf, BSIZE);
            b = atoi(buf);
            // обрабатываем полученные данные
            result = a + b;
            // выводим результат на экран
            wsprintf(buf, "%d", result);
            SetDlgItemText(hwndDlg, IDC_EDIT_RESULT, buf);
        }
        break;
    case WM_CLOSE:
        EndDialog(hwndDlg, NULL);
        break;
    }

    return 0;
}

INT_PTR CALLBACK EditWndProc(HWND hEdit,
                            UINT uMsg,
                            WPARAM wParam,
                            LPARAM lParam)
{
    switch(uMsg) {
    case WM_CHAR:
        // игнорируем ввод всех символов кроме цифр
        if (0 <= LOWORD(lParam) && LOWORD(lParam) <= 9) {
            CallWindowProc(OldWndProc, hEdit, uMsg, wParam, lParam);
        }
        break;
    default:
            CallWindowProc(OldWndProc, hEdit, uMsg, wParam, lParam);
        break;
    }
    return 0;
}
res.rc
Код:
// Generated by ResEdit 1.5.11
// Copyright (C) 2006-2012
// http://www.resedit.net

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




//
// Dialog resources
//
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
IDD_DIALOG1 DIALOG 0, 0, 310, 142
STYLE DS_3DLOOK | DS_CENTER | DS_MODALFRAME | DS_SHELLFONT | WS_CAPTION | WS_VISIBLE | WS_POPUP | WS_SYSMENU
CAPTION "a + b = result"
FONT 8, "Ms Shell Dlg"
{
    DEFPUSHBUTTON   "OK", IDOK, 73, 98, 50, 14
    PUSHBUTTON      "Cancel", IDCANCEL, 184, 98, 50, 14
    EDITTEXT        IDC_EDIT_A, 45, 44, 40, 14, ES_AUTOHSCROLL
    EDITTEXT        IDC_EDIT_B, 131, 44, 40, 14, ES_AUTOHSCROLL
    EDITTEXT        IDC_EDIT_RESULT, 225, 44, 40, 14, ES_AUTOHSCROLL
    LTEXT           "a", IDC_STATIC_A, 62, 32, 5, 8, SS_LEFT
    LTEXT           "b", IDC_STATIC_B, 148, 32, 5, 8, SS_LEFT
    LTEXT           "Result", IDC_STATIC_RESULT, 234, 32, 21, 8, SS_LEFT
    LTEXT           "+", IDC_STATIC_PLUS, 107, 45, 5, 8, SS_LEFT
    LTEXT           "=", IDC_STATIC_EQUAL, 197, 45, 5, 8, SS_LEFT
}
resource.h
Код:
#ifndef IDC_STATIC
#define IDC_STATIC (-1)
#endif

#define IDD_DIALOG1                             100
#define IDC_STATIC_A                            1005
#define IDC_STATIC_B                            1006
#define IDC_STATIC_RESULT                       1007
#define IDC_STATIC_PLUS                         1009
#define IDC_STATIC_EQUAL                        1010
#define IDC_EDIT_A                              1011
#define IDC_EDIT_B                              1012
#define IDC_EDIT_RESULT                         1013
8Observer8 вне форума Ответить с цитированием
Старый 05.05.2012, 23:17   #2
s-andriano
Старожил
 
Аватар для s-andriano
 
Регистрация: 08.04.2012
Сообщений: 3,229
По умолчанию

1. Что-то мне помнится, в свойствах эдита можно установить, что он принимает только цифры.
2. Не помню приоритет операций в С, но если бы аналогичное было записано на Паскале:
(0 <= LOWORD(lParam) && LOWORD(lParam) <= 9)
то работало бы неправильно из-за отсутствия скобок.

Кажется, так: ES_NUMBER

Последний раз редактировалось s-andriano; 05.05.2012 в 23:20.
s-andriano вне форума Ответить с цитированием
Старый 06.05.2012, 07:09   #3
8Observer8
Старожил
 
Аватар для 8Observer8
 
Регистрация: 02.01.2011
Сообщений: 3,323
По умолчанию

Цитата:
Сообщение от s-andriano Посмотреть сообщение
1. Что-то мне помнится, в свойствах эдита можно установить, что он принимает только цифры.
Благодарю! Пока сделаю с ES_NUMBER.

Как теперь реализовать идею: при вводе "не цифр" выводить строку красного цвета "Вводите только цифры!" рядом с Edit'ом . Мне кажется, без сабклассинга не обойтись. Мне нужна эта секция: case WM_CHAR, для анализа вводимых символов.

Цитата:
Сообщение от s-andriano Посмотреть сообщение
2. Не помню приоритет операций в С, но если бы аналогичное было записано на Паскале:
(0 <= LOWORD(lParam) && LOWORD(lParam) <= 9)
то работало бы неправильно из-за отсутствия скобок.
Здесь всё правильно. Приоритет "<=" выше, чем приоритет "&&"
8Observer8 вне форума Ответить с цитированием
Старый 06.05.2012, 09:32   #4
EUGY
Форумчанин
 
Аватар для EUGY
 
Регистрация: 11.07.2010
Сообщений: 914
По умолчанию

Потому как надо: return CallWindowProc(OldWndProc,....
а не return 0, как у Вас сейчас.
EUGY вне форума Ответить с цитированием
Старый 06.05.2012, 15:45   #5
8Observer8
Старожил
 
Аватар для 8Observer8
 
Регистрация: 02.01.2011
Сообщений: 3,323
По умолчанию

EUGY, большое спасибо! Это всё моя невнимательность.

Я нашёл ещё ошибки:

Вместо:
Код:
    case WM_CHAR:
        // игнорируем ввод всех символов кроме цифр
        if (0 <= LOWORD(lParam) && LOWORD(lParam) <= 9) {
            CallWindowProc(OldWndProc, hEdit, uMsg, wParam, lParam);
        }
        break;
Нужно:
Код:
    case WM_CHAR:
        // игнорируем ввод всех символов кроме цифр
        if (('0' <= LOWORD(wParam)) && (LOWORD(wParam) <= '9')) {
            return CallWindowProc(OldWndProc, hEdit, uMsg, wParam, lParam);
        }
        break;
8Observer8 вне форума Ответить с цитированием
Старый 06.05.2012, 15:50   #6
EUGY
Форумчанин
 
Аватар для EUGY
 
Регистрация: 11.07.2010
Сообщений: 914
По умолчанию

Чтоб не путаться оставьте return CallWindowProc только в конце оконной процедуры.
Не в case default.

И если нужно, чтобы при некотором сообщении не доходило до дефолта:

Код:
case WM_CHAR:
 if (чего_то_там)
   return 0;
EUGY вне форума Ответить с цитированием
Старый 06.05.2012, 16:39   #7
8Observer8
Старожил
 
Аватар для 8Observer8
 
Регистрация: 02.01.2011
Сообщений: 3,323
По умолчанию

EUGY, у меня сейчас вот так работает:
Код:
INT_PTR CALLBACK EditWndProc(HWND hEdit,
                            UINT uMsg,
                            WPARAM wParam,
                            LPARAM lParam)
{
    switch(uMsg) {
    case WM_CHAR:
        // игнорируем ввод всех символов кроме цифр
        if (('0' <= LOWORD(wParam)) && (LOWORD(wParam) <= '9')) {
            return CallWindowProc(OldWndProc, hEdit, uMsg, wParam, lParam);
        }
        break;
    default:
            return CallWindowProc(OldWndProc, hEdit, uMsg, wParam, lParam);
        break;
    }
    return 0;
}
Если я напишу CallWindowProc в последнем return'e - работать будет не так как нужно. Я правильно понял?
8Observer8 вне форума Ответить с цитированием
Старый 06.05.2012, 16:58   #8
EUGY
Форумчанин
 
Аватар для EUGY
 
Регистрация: 11.07.2010
Сообщений: 914
По умолчанию

Вот я бы написал так, просто как болванка, не принимайте за эталон:
Код:
#include "stdafx.h"
#include <windows.h>
#include "resource.h"


LRESULT CALLBACK EditWndProc(HWND hwnd, UINT uMsg,	 WPARAM wParam, LPARAM lParam)
{
	switch (uMsg)
	{
	case WM_CHAR:
		if (LOWORD(wParam) < '0'  || LOWORD(wParam) > '9')
			return 0;
		break;
	}

	return CallWindowProc((WNDPROC)GetProp(hwnd, TEXT("WNDPROC")),hwnd,uMsg,wParam,lParam);
}

INT_PTR CALLBACK BasicDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
	switch(uMsg)
	{
	case WM_INITDIALOG:
		HWND hEdit = GetDlgItem(hwndDlg, IDC_EDIT1);
		SetProp(hEdit,TEXT("WNDPROC"),(HANDLE)SetWindowLong(hEdit, GWL_WNDPROC, (LONG)EditWndProc));
		break;
	}
	return 0;
}


int _stdcall WinMain(HINSTANCE hInst,HINSTANCE,LPSTR,int)
{
	return DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_DIALOG1), NULL, BasicDialogProc, NULL);
}

Последний раз редактировалось EUGY; 06.05.2012 в 17:07. Причина: поправил параметр в WinMain
EUGY вне форума Ответить с цитированием
Старый 06.05.2012, 17:20   #9
8Observer8
Старожил
 
Аватар для 8Observer8
 
Регистрация: 02.01.2011
Сообщений: 3,323
По умолчанию

Точно! Теперь понял! Спасибо!
8Observer8 вне форума Ответить с цитированием
Старый 07.05.2012, 10:01   #10
8Observer8
Старожил
 
Аватар для 8Observer8
 
Регистрация: 02.01.2011
Сообщений: 3,323
По умолчанию

Я доделал программу! При вводе "не цифры" выскакивает сообщение:



Я предусмотрел удаление цифр с помощью клавиши "Backspace" (VK_BACK). Возник вопрос: почему секция WM_CHAR не срабатывает при нажатии на клавишу "Delete"? Заранее спасибо за ответ!

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

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

LPCTSTR szDlgName = MAKEINTRESOURCE(IDD_DIALOG1);

INT_PTR CALLBACK EditWndProc(HWND hEdit,
                            UINT uMsg,
                            WPARAM wParam,
                            LPARAM lParam );

int WINAPI WinMain(HINSTANCE hInstance,
                   HINSTANCE hPrevInstance,
                   LPSTR lpCmdLine,
                   int nCmdShow)
{
    return DialogBoxParam(hInstance, szDlgName, NULL, BasicDialogProc, (LPARAM ) NULL);
}

#define BSIZE 512
char buf[BSIZE];
int a;
int b;
int result;
long OldWndProc;
HWND hEdit_A;
HWND hEdit_B;
HWND hDlg;

INT_PTR CALLBACK BasicDialogProc(HWND hwndDlg,
                            UINT uMsg,
                            WPARAM wParam,
                            LPARAM lParam )
{
    switch (uMsg) {
    case WM_INITDIALOG:
        hDlg = hwndDlg;
        // инициализируем Edit'ы
        SetDlgItemText(hwndDlg, IDC_EDIT_A, "0");
        SetDlgItemText(hwndDlg, IDC_EDIT_B, "0");
        SetDlgItemText(hwndDlg, IDC_EDIT_RESULT, "0");

        // замещаем адpес оpигинальной пpоцедуpы окна нашим собственным адpесом
        hEdit_A = GetDlgItem(hwndDlg, IDC_EDIT_A);
        hEdit_B = GetDlgItem(hwndDlg, IDC_EDIT_B);
        OldWndProc = SetWindowLong(hEdit_A, GWL_WNDPROC, (LONG) EditWndProc);
        SetWindowLong(hEdit_B, GWL_WNDPROC, (LONG) EditWndProc);

        // ограничим количество вводимых символов
        SendMessage(hEdit_A, EM_LIMITTEXT, 7, 0);
        SendMessage(hEdit_B, EM_LIMITTEXT, 7, 0);
        break;
    case WM_COMMAND:
        // нажатием на кнопку Cancel, закрываем окно
        if (LOWORD(wParam) == IDCANCEL) {
            SendMessage(hwndDlg, WM_CLOSE, 0, 0);

        // нажатием на кнопку Ok, обрабатываем данные
        } else if (LOWORD(wParam) == IDOK) {
            // получаем первое число
            GetDlgItemText(hwndDlg, IDC_EDIT_A, buf, BSIZE);
            a = atoi(buf);
            // получаем второе число
            GetDlgItemText(hwndDlg, IDC_EDIT_B, buf, BSIZE);
            b = atoi(buf);
            // обрабатываем полученные данные
            result = a + b;
            // выводим результат на экран
            wsprintf(buf, "%d", result);
            SetDlgItemText(hwndDlg, IDC_EDIT_RESULT, buf);
        }
        break;
    case WM_CLOSE:
        EndDialog(hwndDlg, (INT_PTR) NULL);
        break;
    }

    return 0;
}

INT_PTR CALLBACK EditWndProc(HWND hEdit,
                            UINT uMsg,
                            WPARAM wParam,
                            LPARAM lParam)
{
    switch(uMsg) {
    case WM_CHAR:
        // игнорируем ввод всех символов кроме цифр
        if (LOWORD(wParam) != VK_BACK && (LOWORD(wParam) < '0' || '9' < LOWORD(wParam))) {
            MessageBox(hDlg, "Write only numbers", "Warning", 0);
            return 0;
        }
        break;
    }
    return CallWindowProc((WNDPROC) OldWndProc, hEdit, uMsg, wParam, lParam);
}
res.rc
Код:
// Generated by ResEdit 1.5.11
// Copyright (C) 2006-2012
// http://www.resedit.net

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




//
// Dialog resources
//
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
IDD_DIALOG1 DIALOG 0, 0, 310, 142
STYLE DS_3DLOOK | DS_CENTER | DS_MODALFRAME | DS_SHELLFONT | WS_CAPTION | WS_VISIBLE | WS_POPUP | WS_SYSMENU | WS_MINIMIZEBOX
CAPTION "a + b = result"
FONT 8, "Ms Shell Dlg"
{
    DEFPUSHBUTTON   "OK", IDOK, 73, 98, 50, 14
    PUSHBUTTON      "Cancel", IDCANCEL, 184, 98, 50, 14
    EDITTEXT        IDC_EDIT_A, 45, 44, 40, 14, ES_AUTOHSCROLL | ES_RIGHT
    EDITTEXT        IDC_EDIT_B, 131, 44, 40, 14, ES_AUTOHSCROLL | ES_RIGHT
    EDITTEXT        IDC_EDIT_RESULT, 225, 44, 40, 14, ES_AUTOHSCROLL | ES_READONLY | ES_RIGHT
    LTEXT           "a", IDC_STATIC_A, 62, 32, 5, 8, SS_LEFT
    LTEXT           "b", IDC_STATIC_B, 148, 32, 5, 8, SS_LEFT
    LTEXT           "Result", IDC_STATIC_RESULT, 234, 32, 21, 8, SS_LEFT
    LTEXT           "+", IDC_STATIC_PLUS, 107, 45, 5, 8, SS_LEFT
    LTEXT           "=", IDC_STATIC_EQUAL, 197, 45, 5, 8, SS_LEFT
}
8Observer8 вне форума Ответить с цитированием
Ответ


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



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Ограничение ввода в stringgrid Человек Панда Помощь студентам 1 10.07.2011 11:04
Ограничение ввода с клавиатуры jekidollar Общие вопросы C/C++ 1 12.05.2010 08:23
Ограничение ввода в Edit xxxsas Общие вопросы C/C++ 4 22.01.2009 12:36
Ограничение ввода символов. Delphi Alex_2017 Помощь студентам 0 04.06.2008 17:26
Ограничение ввода в Edit Макс84 Компоненты Delphi 7 23.07.2007 09:38