Paulo Nobre Postado Abril 2, 2006 Denunciar Share Postado Abril 2, 2006 Prezados ColegasGostaria de saber como faço para mudar o meu cursorfora do domínio do programa, ou seja, que ele assuma,por exemplo o formato de uma cruz quando estiver em cima do screen.Só estou conseguindo fazer isto em cima do form.Estou fazendo screen.cursor:= crCross, porém, só aparece a cruz em cima do forme não na tela toda.ObrigadoPaulo Nobre Citar Link para o comentário Compartilhar em outros sites More sharing options...
0 Denis Bittencourt Muniz Postado Abril 3, 2006 Denunciar Share Postado Abril 3, 2006 Você pode usar as API's do Windows: 'SetCursor', para trocar o cursor do sistema.'LoadCursor', se necessário carregar algum arquivo 'cur' (arquivo de cursor).'DestroyCursor', se você usou 'LoadCursor' para carrgar um arquivo 'cur'.Mais detalhes sobre API's do Windows: www.allapi.netFalows! Qualquer coisa 'stamos aí! Citar Link para o comentário Compartilhar em outros sites More sharing options...
0 Paulo Nobre Postado Abril 3, 2006 Autor Denunciar Share Postado Abril 3, 2006 Denis obrigado pela atenção.Você pode me dizer se estas funções estão "encapsuladas"(nem sei se é este o termo), em alguma UNIT do delphi, por exemplo a WINDOWS. Estou sem o delphi neste momento.Pelo que você colocou talvez eu precise apenas da função setcursor, pois usarei apenas o cursor cross num determinado momento e depois voltarei para o padrão. Citar Link para o comentário Compartilhar em outros sites More sharing options...
0 Denis Bittencourt Muniz Postado Abril 3, 2006 Denunciar Share Postado Abril 3, 2006 As três funções, mais algumas (comparado com o número real existente) API's do Windows, estão na unit Windows. Falows! Citar Link para o comentário Compartilhar em outros sites More sharing options...
0 Paulo Nobre Postado Abril 3, 2006 Autor Denunciar Share Postado Abril 3, 2006 Mais detalhes sobre API's do Windows: www.allapi.net - Mencionou o colega DenisNo site acima sugerido pelo Denis existe um programa que contém todas(ou quase todas) APIS do windows.Acontece que os exemplos são todos para VB e VB.net, que não estou acostumado.O delphi nos acostumou mal com o uso das APIs( sem álias user lib etc...)Alguém que já precisou mudar o cursor e depois voltar para o defaut poderia me ajudar postando o código de como fazer isto.Gostaria de passar para crCross e depois voltar para o default.Ficaria muito grato. Citar Link para o comentário Compartilhar em outros sites More sharing options...
0 s3c Postado Abril 3, 2006 Denunciar Share Postado Abril 3, 2006 Tente utilizar:SetSystemCursor(LoadCursor(0, IDC_Cross), OCR_Normal);Para mudar e voltar o cursor. Citar Link para o comentário Compartilhar em outros sites More sharing options...
0 Paulo Nobre Postado Abril 4, 2006 Autor Denunciar Share Postado Abril 4, 2006 Para voltar seriaSetSystemCursor(LoadCursor(0, IDC_Normal), OCR_Normal);ouSetSystemCursor(Screen.cursor[crNormal]), OCR_Normal); Citar Link para o comentário Compartilhar em outros sites More sharing options...
0 s3c Postado Abril 4, 2006 Denunciar Share Postado Abril 4, 2006 Pode parecer estranho mas para voltar o cursor é o mesmo comando.Não conseguí entender muito bem, mas pelo que ví, a função SetSystemCursor destroi o cursor que ela ativa e quando você aplica o mesmo comando, como o cursor não existe mais, ela volta ao cursor anterior. Citar Link para o comentário Compartilhar em outros sites More sharing options...
0 Paulo Nobre Postado Abril 4, 2006 Autor Denunciar Share Postado Abril 4, 2006 É realmente estranho, vou testar o código mais tarde.Obrigado s3c Citar Link para o comentário Compartilhar em outros sites More sharing options...
0 Micheus Postado Abril 4, 2006 Denunciar Share Postado Abril 4, 2006 Faça o seguinte:altere o comando utilizando os cursores OCR_SIZENS (resize norte/sul) pelo IDC_SIZEWE (resize leste/oeste)procedure TForm1.Button1Click(Sender: TObject); begin SetSystemCursor(LoadCursor(0, IDC_SIZEWE), OCR_SIZENS); end;Agora será possível entender porque a restauração é feita utilizando o mesmo comando. Clique no botão, vá até as bordas de uma janela (norte, sul, leste e oeste) e observe que na verdade o que ocorre é um swap (troca) entre os cursores!!![]s Citar Link para o comentário Compartilhar em outros sites More sharing options...
0 Paulo Nobre Postado Abril 5, 2006 Autor Denunciar Share Postado Abril 5, 2006 É verdade mas no meu caso preciso mudar da cruz para a seta(normal).O que foi fornecido pelo s3c funciona perfeitamente porém, estou com um problema que não consigo resolver. Fiquei ontem umas 4 horas em cima e nada.Veja se vocês podem me ajudar.Preciso, que ao clicar na tecla F3 o cursor mude para cruz e ao soltar a F3 volte para a seta(normal).Alguém diria, por exemplo coloque no onkeydown SetSystemCursor(LoadCursor(0, IDC_Normal), OCR_Normal); e depois no onkeyup SetSystemCursor(LoadCursor(0, IDC_Normal), OCR_Normal);fazendo a chamada por if key = VK_F3 then.O problema é que meu programa, que é um capturador da parte da tela do screen, funciona da seguinte maneira:Você fica com f3 clicada(enquanto isto o código de captura está sendo executado) e arrasta o mouse. Nesta arrastada do mouse é que o cursor muda para a cruz.Só que quando solto(onkeyup) ora o cursor termina na cruz ora termina na seta(onkeyup). Parece que ficar com F3 clicada equivale a ficar fazendo apertar(down) e soltar(up) um número n de vezes.Já tentei de tudo:Coloquei uma variável inteira para ver quantas vezes a tecla f3 ficou premida no onkeydown e verificar no onkeyup se é para ou ímpar no keyup e com um if ver se precisofazer duas vezes SetSystemCursor(LoadCursor(0, IDC_Normal), OCR_Normal); ou uma .Fiz a mesma coisa jogando para o registro e fazendo a leitura no registro pelo onkeyup.Só que nada deu certo.Sempre na saída do onkeyup o resultado é aleatório ora termina na cruz ora termina na seta. Eu preciso que termine na seta.Engraçado é que achava que tinha que dar certo pois se fosse ímpar o número de vezes(descobria pelo uso do MOD) você estava indo para a seta e se fosse para voltando para a cruz. Aí fazendo a leitura com um if você acertava no final?Alguém poderia me ajudar com algum código?Obrigado. Citar Link para o comentário Compartilhar em outros sites More sharing options...
0 s3c Postado Abril 5, 2006 Denunciar Share Postado Abril 5, 2006 Tente utilizar uma variável boolean: var bF3:Boolean; procedure TForm1.FormCreate(Sender: TObject); begin bF3 := false; end; procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin if (key = VK_F3) and not bF3 then begin bF3 := true; SetSystemCursor(LoadCursor(0, IDC_Cross), OCR_Normal); end; end; procedure TForm1.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); begin if (key = VK_F3) and bF3 then begin bF3 := false; SetSystemCursor(LoadCursor(0, IDC_Cross), OCR_Normal); end; end;Mas o formulário tem que estar em foco no onKeyDown e onKeyUp Citar Link para o comentário Compartilhar em outros sites More sharing options...
0 Micheus Postado Abril 6, 2006 Denunciar Share Postado Abril 6, 2006 Talvez você esteja utilizando, mas pelo sim pelo não: acredito que você também vá precisar utilizar a função SetCaptureControl, para capturar os eventos do mouse fora de sua aplicação. Citar Link para o comentário Compartilhar em outros sites More sharing options...
0 Paulo Nobre Postado Abril 6, 2006 Autor Denunciar Share Postado Abril 6, 2006 Tente utilizar uma variável boolean: var bF3:Boolean; procedure TForm1.FormCreate(Sender: TObject); begin bF3 := false; end; procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin if (key = VK_F3) and not bF3 then begin bF3 := true; SetSystemCursor(LoadCursor(0, IDC_Cross), OCR_Normal); end; end; procedure TForm1.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); begin if (key = VK_F3) and bF3 then begin bF3 := false; SetSystemCursor(LoadCursor(0, IDC_Cross), OCR_Normal); end; end;Mas o formulário tem que estar em foco no onKeyDown e onKeyUpO problema é que a minha aplicação estará rodando no tray, fora de foco.Teria como adaptar para quando estiver fora de foco?Não conheço esta função SetCaptureControl.Teria como adaptar para o código do s3c? Citar Link para o comentário Compartilhar em outros sites More sharing options...
0 Micheus Postado Abril 6, 2006 Denunciar Share Postado Abril 6, 2006 Sim. Coloque dentro do if do KeyDown coloque o SetCaptureControl(Self) (self - seu form recebe as mensagens) e no if do KeyUp coloque o ReleaseCapture.p.s. Nunca realizei este procedimento sem que o form estivesse visível. Não estou certo de que lhe servirá. Também para o caso que utilizei, ocorre que a coordenada tinha que ser remapeada com ScreenToClient (ou algo assim). Citar Link para o comentário Compartilhar em outros sites More sharing options...
0 s3c Postado Abril 6, 2006 Denunciar Share Postado Abril 6, 2006 Sim. Coloque dentro do if do KeyDown coloque o SetCaptureControl(Self) (self - seu form recebe as mensagens) e no if do KeyUp coloque o ReleaseCapture.Acho que o primeiro problema não é capturar o mouse fora da aplicação e sim capturar a tecla F3 fora da aplicação.Particularmente só conheço uma maneira de se fazer; com funções Hook (SetWindowsHookEx com idHook = WH_KeyBoard, CallNextHookEx e UnhookWindowsHookEx). Essas hooks devem ser globais e portanto precisam estar rodando numa dll.Espero que algum colega do fórum conheça uma maneira mais simples de capturar teclas fora da aplicação. Citar Link para o comentário Compartilhar em outros sites More sharing options...
0 Denis Bittencourt Muniz Postado Abril 7, 2006 Denunciar Share Postado Abril 7, 2006 Espero que algum colega do fórum conheça uma maneira mais simples de capturar teclas fora da aplicação.Não, não tem... Hooks (ganchos) são mecanismos de envio de informações entre uma aplicação e um objeto existente, um hardware, por exemplo... No caso acima, sua aplicação teria que ganchar o teclado, assim obtendo todos os eventos do mesmo.. Lembro de ter usado essas API's para ganchar uma caixa de mensagem (MessageBox), assim tendo total controle sobre a caixa de mensagem (alterei o rotúlo dos botões 'Sim' e 'Não'. Alterei também os tamanhos dos botões).É um processo um pouco complicado, mas um resultado de tirar o chapéu : )Falows! Citar Link para o comentário Compartilhar em outros sites More sharing options...
0 Paulo Nobre Postado Abril 7, 2006 Autor Denunciar Share Postado Abril 7, 2006 Pelo tudo que vi escrito vejo que seria complicado.Vou deixar um pouco este projeto de lado e partir para outros estudos.Mesmo não conseguindo aprendi muito aqui neste tópico.A única coisa que fico intrigado é que vi este procedimentono programa DGMScreen(capturas de telas, janelas e partes)e o programa não tinha nenhuma dll(acho).Ele era fornecido com um executável e um aquivo INI.Obrigado Citar Link para o comentário Compartilhar em outros sites More sharing options...
0 Micheus Postado Abril 7, 2006 Denunciar Share Postado Abril 7, 2006 Paulo, eu até tinha uma versão antiga utilizada no tempo do Pascal for Windows (só uns 10 anos), porém após tentar adaptar não funcionou a contento. Então, fazendo uso do jargão do meu rodapé, dei umas fuçadas e acho que irá servir para o que você quer.Código da DLL:library keyhook; uses Windows, Messages; const WH_KEYBOARD_LL = 13; LLKHF_UP = $8; type PKBDLLHOOKSTRUCT = ^TKBDLLHOOKSTRUCT; TKBDLLHOOKSTRUCT = packed record vkCode :DWORD; scanCode :DWORD; flags :DWORD; time :DWORD; dwExtraInfo :^ULONG; end; var HKeyHook :HHook; WndHandle :THandle; function KeyboardHookProc(Code: Integer; wParam: Word; lParam: Longint): LongInt; stdcall; var KeyMessage :Integer; PKeyStruct :PKBDLLHOOKSTRUCT; begin if Code >= 0 then if (wParam = WM_KEYDOWN) or (wParam = WM_KEYUP) then begin PKeyStruct := PKBDLLHOOKSTRUCT(lParam); if PKeyStruct^.vkCode = VK_F3 then begin PostMessage(WndHandle, wParam, PKeyStruct^.vkCode, 0); // passa apenas o código da tecla Result := 1; // Não deixa outro aplicativo processar a tecla Exit; end; end; Result := CallNextHookEx(HKeyHook, code, wParam, lParam); // Passa evento para outros ganchos end; function InstallKeyHook(FormHandle :THandle): LongInt; stdcall; begin WndHandle := FormHandle; HKeyHook := SetWindowsHookEx(WH_KEYBOARD_LL, @KeyboardHookProc, hInstance, 0); if HKeyHook = 0 then Result := GetLastError else Result := 0; end; procedure UninstallKeyHook; stdcall; begin UnhookWindowsHookEx(HKeyHook); end; exports InstallKeyHook; exports UninstallKeyHook; begin end. link de ref. da função (callback): http://msdn.microsoft.com/library/default....eyboardProc.asp Supondo o form principal do seu projeto seja Form2: ... implementation {$R *.DFM} // carga dinâmica da DLL function InstallKeyHook(FormHandle :THandle): LongInt; stdcall; external 'keyhook.dll'; procedure UninstallKeyHook; stdcall; external 'keyhook.dll'; procedure TForm2.FormCreate(Sender: TObject); begin if InstallKeyHook(Handle) <> 0 then ShowMessage('Houve um erro inicializando a Hook!'); end; procedure TForm2.FormDestroy(Sender: TObject); begin UninstallKeyHook; end; ... Em meus testes funcionou.[]s Citar Link para o comentário Compartilhar em outros sites More sharing options...
0 s3c Postado Abril 7, 2006 Denunciar Share Postado Abril 7, 2006 A única coisa que fico intrigado é que vi este procedimentono programa DGMScreen(capturas de telas, janelas e partes)e o programa não tinha nenhuma dll(acho).Ele era fornecido com um executável e um aquivo INI.Se não tiver outra maneira, a dll de funções hook poderia estar no .exe como um arquivo de recursos. Citar Link para o comentário Compartilhar em outros sites More sharing options...
0 Paulo Nobre Postado Abril 7, 2006 Autor Denunciar Share Postado Abril 7, 2006 Realmente s3c, pode ser que o programa que citei tenha uma dll embutida no arquivo de recursos.Pensei até em manadr um email para o autor do programa e perguntar a ele.Micheus muito muito agradecido por você colocar o código da dll, realmente sozinho não conseguiria nunca escrever este código.Vou adaptar para o meu programa no final de semana. Citar Link para o comentário Compartilhar em outros sites More sharing options...
0 Micheus Postado Abril 8, 2006 Denunciar Share Postado Abril 8, 2006 Quando estava tentando reimplementar este recurso, também achei que poderia faze-la funcionar dentro do executável, porém não estava funcionando. O programa não interseptava a tecla. Porém, utilizava o filtro WH_KEYBOARD. Não tentei verificar se foi algum outro procedimento incorreto que realizei, para o uso deste filtro.Após implementar utilizando o filtro WH_KEYBOARD_LL, que postei anteriormente, resolvi tentar novamente juntar tudo no executável e a resposta foi positiva - Funciona. Assim sendo, você pode colocar todo o código da DLL dentro do executável e retirar do mesmo a carga dinâmica da DLL.Lembrei depois que você quer verificar a tecla control pressionada, um meio de fazer isto é adicionar algo comoCTRLPressed := (GetAsyncKeyState(VK_CONTROL) and $8000) <> 0;na callback, para que você apenas chame seu aplicativo com a combinação CTRL+F3.[]sp.s. valeu pela oportunidade de aprender mais esta. Citar Link para o comentário Compartilhar em outros sites More sharing options...
0 Paulo Nobre Postado Abril 8, 2006 Autor Denunciar Share Postado Abril 8, 2006 Micheus,Testei o código e a dll colocando setsystemcursor no onkeydown e onkeyup e funcionou porém, estou com o seguinte problema: O código que era para ser executado quando apertasse F3 não está sendo executado o programa fica parado.Lembro que o objetivo da captura da tecla F3 era para o seguinte:Clicando na F3 e segurando o cursor passava para uma cruz, arrastava uma parte do screen, soltava a tecla ele voltava para o padrão e este pedaço da tela era capturado.Quando o usuário clica em capturar parte da tecla um timer é acionado (veja abaixo)O código que é executado é o seguinte:Será que o GETKeyState está causando algum problema.procedure TfrmPrincipal.TimerParteDaTelaTimer(Sender: TObject); Var formato : Word; dados : Cardinal; paleta : HPALETTE; begin TimerParteDaTela.Enabled:= False; try if GetKeyState(VK_F3) < 0 then begin Capturando := True; if X1 = 0 then begin X1 := Mouse.CursorPos.X; Y1 := Mouse.CursorPos.Y; X2 := X1; Y2 := Y1; end else if (X2 <> Mouse.CursorPos.X) or (Y2 <> Mouse.CursorPos.Y) then begin Canv.Rectangle(X1, Y1, X2, Y2); X2 := Mouse.CursorPos.X; Y2 := Mouse.CursorPos.Y; Canv.Rectangle(X1, Y1, X2, Y2); end; end else if Capturando then begin Canv.Rectangle(X1, Y1, X2, Y2); Timer1.Enabled:=True; CopiaTela(Image1.Picture.Bitmap, X1, Y1, X2, Y2); Image1.Picture.SaveToClipBoardFormat(formato, dados, paleta); ClipBoard.SetAsHandle(formato, dados); X1 := 0; Capturando := False; end Else begin //SetSystemCursor(LoadCursor(0,IDC_Cross),OCR_Normal); end; finally TimerParteDaTela.Enabled:= True; end; end;É possível contornar este problema?Obrigado. Citar Link para o comentário Compartilhar em outros sites More sharing options...
0 Micheus Postado Abril 9, 2006 Denunciar Share Postado Abril 9, 2006 Paulo, não entendi ao certo a aplicação do timer para a captura. Nas rotinas similares que já fiz, simplesmente tilizava os eventos do Mouse para capturar a posição e movimentação do mesmo, juntamente com variáveis de controle (como seria o caso da VK_F3 pressionada). você nem precisaria chamar esta funçao se ao ser pressionada a tecla F3 você utilizasse uma variável booleana para indicar isto. Dentro do que eu tinha proposto anteriormente, incrementei mais um pouco o programa que fiz e percebí que mesmo utilizando SetCapture, quando o meu form, não está visível, ou seja, quando clico numa área da janela em que o mesmo não está, o foco passa para a janela onde cliquei. Isto estava descrito no help:Also, even if the foreground window has captured the mouse, the user can still click another window, bringing it to the foreground.Bom, parece que ficou um pouco mais complicado. Então imaginei o seguinte, se você ao pressionar sua combinação de teclas, capturar a área da screen (http://www.swissdelphicenter.ch/torry/showcode.php?id=259) e então abrir a janela do seu aplicativo maximizada, sem bordas e com um image (alinhado a área client) contendo a imagem capturada, você poderia utilizar os eventos do mouse direto sobre seu form, e assim marcar e capturar parte da imagem. Assim que você largar o mouse, seu form "some" e tudo fica parecendo ok.Um lance legal para marcar a área delimitada é utilizar a função da API DrawFocusRect, quando você desenha nas coordenas do retangulo pela primeira vez o retângulo pontilhado aparece, quando você a desenha na mesma posição o retangulo desaparece, facilitando bastante a criação do visual da área selecionada. Citar Link para o comentário Compartilhar em outros sites More sharing options...
0 Paulo Nobre Postado Abril 9, 2006 Autor Denunciar Share Postado Abril 9, 2006 Ok, Micheus, muito obrigado.Vou fazer uma análise detalhada do programa e tentar mecher nele. Citar Link para o comentário Compartilhar em outros sites More sharing options...
Pergunta
Paulo Nobre
Prezados Colegas
Gostaria de saber como faço para mudar o meu cursor
fora do domínio do programa, ou seja, que ele assuma,
por exemplo o formato de uma cruz quando estiver em cima do screen.
Só estou conseguindo fazer isto em cima do form.
Estou fazendo screen.cursor:= crCross, porém, só aparece a cruz em cima do form
e não na tela toda.
Obrigado
Paulo Nobre
Link para o comentário
Compartilhar em outros sites
24 respostass a esta questão
Posts Recomendados
Participe da discussão
Você pode postar agora e se registrar depois. Se você já tem uma conta, acesse agora para postar com sua conta.