Из объявленных вами переменных вы инициализировали (пользовательский ввод) только p1
и p2
; остальные P,p,R,r,S,s
из них все еще неинициализированы и имеют мусорное значение.
Далее в программе вы сравниваете их с p1
и p2
. Это неопределенное поведение . Поэтому инициализируйте их перед выполнением операции сравнения с ними.
Просто для разъяснения; P,p,R,r,S,s
называются идентификаторами, и вам необходимо значение float
, чтобы присвоить их (поскольку они имеют тип float
).
Скорее всего, вам нужно char
вместо float
.
char p1, p2;
std::cin >>p1 >> p2;
для сравнения вы должны сделать
if (std::to_upper(p1) == 'P' && std::to_upper(p2) == 'R')
^^^^^^^^^^^^^^ ^^^^ ^^^^^^^^^^^^^^ ^^^^
Обратите внимание, что std :: toupper предназначен для преобразования символа в верхний регистр, что уменьшит количество проверок, что вы сделали.
Хотя вам нужно проверить, являются ли p1
и p2
какие-либо из 'P'
, 'R'
или 'S'
, равны ли они.
Используя троичный оператор , можно написать один код лайнера следующим образом:
#include
#include // std::toupper
int main()
{
std::cout << "Input Player 1 and Player 2 Choices\n";
char p1, p2; std::cin >> p1 >> p2;
p1 = std::toupper(p1); // convert to upper case
p2 = std::toupper(p2); // convert to upper case
std::cout << (
(p1 == p2 && (p1 == 'P' || p1 == 'R' || p1 == 'S')) ? "tie\n"
: (p1 == 'P' && p2 == 'R') || (p1 == 'R' && p2 == 'P') ? "Paper covers rock!\n"
: (p1 == 'S' && p2 == 'R') || (p1 == 'R' && p2 == 'S') ? "Rock breaks scissors!\n"
: (p1 == 'S' && p2 == 'P') || (p1 == 'P' && p2 == 'S') ? "Scissors cut paper!\n"
: "Wrong input!\n"
);
return 0;
}
WM_MENUSELECT действительно обрабатывается для пунктов меню во всплывающих меню также, но не окнами proc формы, содержащей (раскрывающееся) меню, но невидимым окном помощника, созданным Меню. PopupList. К счастью Вы можете (по крайней мере, под Delphi 5), достигают этот HWND с помощью Меню. PopupList. Окно.
Теперь можно использовать старомодный способ разделить окно на подклассы, как описано, например, в этой статье CodeGear, обработать WM_MENUSELECT также для всплывающих меню. HWND будет допустим от того, после того, как первый TPopupMenu будет создан к тому, прежде чем последний объект TPopupMenu будет уничтожен.
Быстрый тест с демонстрационным приложением в связанной статье в вопросе должен показать, собирается ли это работать.
Править: Это действительно работает. Я изменил связанный пример для показа подсказок также для всплывающего меню. Вот шаги:
Добавьте обработчик для OnDestroy, членскую переменную для старого окна proc и метода для нового окна proc к форме:
TForm1 = class(TForm)
...
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure ApplicationEvents1Hint(Sender: TObject);
private
miHint : TMenuItemHint;
fOldWndProc: TFarProc;
procedure WMMenuSelect(var Msg: TWMMenuSelect); message WM_MENUSELECT;
procedure PopupListWndProc(var AMsg: TMessage);
end;
Измените обработчик OnCreate формы, чтобы разделить скрытое окно PopupList на подклассы и реализовать надлежащее восстановление окна proc в обработчике OnDestroy:
procedure TForm1.FormCreate(Sender: TObject);
var
NewWndProc: TFarProc;
begin
miHint := TMenuItemHint.Create(self);
NewWndProc := MakeObjectInstance(PopupListWndProc);
fOldWndProc := TFarProc(SetWindowLong(Menus.PopupList.Window, GWL_WNDPROC,
integer(NewWndProc)));
end;
procedure TForm1.FormDestroy(Sender: TObject);
var
NewWndProc: TFarProc;
begin
NewWndProc := TFarProc(SetWindowLong(Menus.PopupList.Window, GWL_WNDPROC,
integer(fOldWndProc)));
FreeObjectInstance(NewWndProc);
end;
Реализуйте разделенное на подклассы окно proc:
procedure TForm1.PopupListWndProc(var AMsg: TMessage);
function FindItemForCommand(APopupMenu: TPopupMenu;
const AMenuMsg: TWMMenuSelect): TMenuItem;
var
SubMenu: HMENU;
begin
Assert(APopupMenu <> nil);
// menuitem
Result := APopupMenu.FindItem(AMenuMsg.IDItem, fkCommand);
if Result = nil then begin
// submenu
SubMenu := GetSubMenu(AMenuMsg.Menu, AMenuMsg.IDItem);
if SubMenu <> 0 then
Result := APopupMenu.FindItem(SubMenu, fkHandle);
end;
end;
var
Msg: TWMMenuSelect;
menuItem: TMenuItem;
MenuIndex: integer;
begin
AMsg.Result := CallWindowProc(fOldWndProc, Menus.PopupList.Window,
AMsg.Msg, AMsg.WParam, AMsg.LParam);
if AMsg.Msg = WM_MENUSELECT then begin
menuItem := nil;
Msg := TWMMenuSelect(AMsg);
if (Msg.MenuFlag <> $FFFF) or (Msg.IDItem <> 0) then begin
for MenuIndex := 0 to PopupList.Count - 1 do begin
menuItem := FindItemForCommand(PopupList.Items[MenuIndex], Msg);
if menuItem <> nil then
break;
end;
end;
miHint.DoActivateHint(menuItem);
end;
end;
Это сделано для всех всплывающих меню в цикле, пока первый объект соответствия или подменю не найден.
Не уверенный, если это помогает, но я создал свое собственное многострочное окно подсказки (для Delphi7), чтобы смочь показать больше затем всего одну строку текста. Это - открытый исходный код, и можно найти его здесь.
Существует включенный показ некоторой работы его на правильном местоположении на экране, но Вы имеете полный контроль над ним.