Вначале немного теории. Windows, судя по названию, это "сборище" окон. Каждое окно обычно содержит другие окна, т.е. является родителем для некоторых других окон (эти "другие окна" называют дочерними). Для нашей программы нам достаточно знать, что то поле, куда мы вводим пароли является хоть и маленьким, но окном. А значит, как и любое порядочное окно, оно имеет параметр "текст окна" и умеет принимать\отсылать сообщения. Именно на данных весьма полезных свойствах полей ввода основаны программы для извлечения паролей из-под "звёздочек".
Function GetText(WindowHandle: hwnd):string;
var
txtLength : integer;buffer: string;
begin//Узнаём длину текста
TxtLength := SendMessage(WindowHandle, WM_GETTEXTLENGTH, 0, 0);if txtlength>0 then
begintxtlength := txtlength + 1;
setlength (buffer, txtlength);//записываем текст окна в buffer
sendmessage(WindowHandle, wm_gettext, txtlength, longint(@buffer[1]));result := buffer;
end else result:='';end;
Теперь, если мы вызовем эту функцию, записав в параметр идентификатор поля ввода пароля, то она возвратит нам сам пароль. Как узнать идентификатор нужного окна будет рассказано далее. А сейчас поговорим о втором способе извлечения пароля. Только в данном способе мы не запишем пароль в какую-либо переменную, а заставим поле ввода отобразить вместо звёздочек нормальные символы. Для этого нужно послать ему сообщение EM_SETPASSWORDCHAR. Вообще, это сообщение используется и для того, чтобы нормальный текст заменить каким-либо символом (обычно используются звёздочки). Далее приведена процедура, которая не просто показывает нормальный текст вместо звёздочек, но, если у выбранного поля ввода текст не зашифрован, то мы заменяем его звёздочками. Т.е., если для поля ввода пароля применить эту процедуру, то появятся нормальные символы, а если для того же поля повторить операцию, то текст опять превратится в звёздочки.
Procedure ShowPass(h:hwnd);var
ch:integer;i:integer;
begin//узнаём, закодирован ли текст
ch:=SendMessage(h, EM_GETPASSWORDCHAR, 0, 0);//если закодирован, то раскодируем текст, иначе кодируем звёздочками
if ch>0 theni:=0
elsei:=ord('*');
SendMessage(h, EM_SETPASSWORDCHAR, i, 0);end;
Теперь можно приступить к созданию самой программы, но перед этим нужно оговорить принципы её функционирования:– пользователь должен как-то указать программе, какой именно пароль он хочет "вскрыть". Наиболее удобным для юзера способом мне представляется следующий: пользователь наводит курсор мышки на поле ввода с нужным паролем, нажимает определённую комбинацию клавиш и получает взамен "звёздочек" нормальный пароль.
1) Заменяем "звёздочки" на обычные символы;
2) Выделяем весь текст в поле ввода;3) Копируем выделенный текст в буфер обмена;
4) Обратно маскируем пароль "звёздочками.Теперь запускаем Delphi и делаем формочку, взяв за образец рис.1.
h:HWND;
ch:Integer;s:String;
Процедура обработки нажатия на кнопку "Показать\Спрятать пароль":procedure TForm1.Button1Click(Sender: TObject);
begin//узнаём координаты курсора мыши
getcursorpos(p);//получаем идентификатор окна, находящегося под курсором мыши
h:=windowfrompoint(p);//прячем\показываем пароль
ShowPass(h);//перерисовываем окно
InvalidateRect(h, nil, true);end;
Данная процедура позволяет маскировать\демаскировать текст почти любого поля ввода.Процедура обработки нажатия на кнопку "Скопировать пароль":
procedure TForm1.Button2Click(Sender: TObject);begin
//узнаём координаты курсора мышиgetcursorpos(p);
//получаем идентификатор окна, находящегося под курсором мышиh:=windowfrompoint(p);
//каким символом замаскирован текст в данном окне?ch:=SendMessage(h, EM_GETPASSWORDCHAR, 0, 0);
//если пароль замаскирован, то показываем его в нормальном видеif ch>0 then
SendMessage(h, EM_SETPASSWORDCHAR, 0, 0);//выделяем весь текст
SendMessage(h, EM_SETSEL, 0, -1);//копируем выделенный текст
SendMessage(h, WM_COPY, 0, 0);//если мы "вскрывали" пароль, то опять маскируем его
if ch>0 thenSendMessage(h,EM_SETPASSWORDCHAR, ch, 0);
//перерисовываем окноInvalidateRect(h, nil, true);
end;Процедура обработки нажатия на кнопку "Показать пароль в отдельном окне":
procedure TForm1.Button3Click(Sender: TObject);
begin//узнаём координаты курсора мыши
getcursorpos(p);//получаем идентификатор окна, находящегося под курсором мыши
h:=windowfrompoint(p);//получаем текст окна
s:=gettext(h);//если текст не является пустой строкой, то показываем его пользователю
if s<>'' thenbegin
setforegroundwindow(form1.handle);showmessage(s);
end;end;
В принципе программа уже готова к эксплуатации. Но для удобства пользователя сделаем, как и собирались, поддержку "горячих клавиш". Для этого мы воспользуемся функцией
RegisterHotKey(HWND hWnd, // этому окну придёт уведомление о нажатии
комбинации клавишint id, // идентификатор "горячих клавиш"
UINT fsModifiers, // должны ли быть нажаты клавиши Ctrl, Shift или AltUINT vk // код клавиши, на которую мы будем реагировать
);Для события OnCreate формы запишите процедуру:
procedure TForm1.FormCreate(Sender: TObject);begin
//регистрируем сочетание Shift+Alt+F9If not RegisterHotkey
(Handle, 1, MOD_ALT or MOD_SHIFT, VK_F9) ThenShowMessage('Нельзя использовать данное сочетание клавиш!');
//регистрируем сочетание Shift+Alt+F8If not RegisterHotkey
(Handle, 2, MOD_ALT or MOD_SHIFT, VK_F8) ThenShowMessage('Нельзя использовать данное сочетание клавиш!');
//регистрируем сочетание Shift+Alt+F7If not RegisterHotkey
(Handle, 3, MOD_ALT or MOD_SHIFT, VK_F7) ThenShowMessage('Нельзя использовать данное сочетание клавиш!');
end;Теперь в секции Private объявите процедуру, которая будет реагировать на нажатие комбинаций клавиш:
Procedure WMHotkey( Var msg: TWMHotkey ); message WM_HOTKEY;
А вот и сама процедура:Procedure TForm1.WMHotkey( Var msg: TWMHotkey );
begincase msg.hotkey of
//если нажато Shift+Alt+F9, то копируем пароль1:begin
getcursorpos(p);h:=windowfrompoint(p);
ch:=SendMessage(h,EM_GETPASSWORDCHAR,0,0);if ch>0 then
SendMessage(h,EM_SETPASSWORDCHAR,0,0);SendMessage(h,EM_SETSEL,0,-1);
SendMessage(h,WM_COPY,0,0);if ch>0 then
SendMessage(h,EM_SETPASSWORDCHAR,ch,0);InvalidateRect(h,nil,true);
end;//если нажато Shift+Alt+F8, то прячем\показываем пароль пароль
2:begingetcursorpos(p);
h:=windowfrompoint(p);ShowPass(h);
InvalidateRect(h,nil,true);end;
//если нажато Shift+Alt+F9, то показываем пароль в отдельном окне3:begin
getcursorpos(p);h:=windowfrompoint(p);
s:=gettext(h);if s<>'' then
begin
setforegroundwindow(form1.handle);showmessage(s);
end;end;
end;end;
P. S.
Разумеется, данную программу нельзя применять ни в каких деструктивных целях.Иван Ширко
ishyrko@gmail.com
Читать дальше >>