
Micheus
Veteranos-
Total de itens
3.189 -
Registro em
-
Última visita
Tudo que Micheus postou
-
Acho que o que o colega Morcego deseja é: não alterar a impressora padrão do sistema, mas sim, a utilizada pelo programa quando manipulando TPrinter. Assim, não testei a impressão direta no canvas, mas testando com a caixa de diálogo de impressão obtive a alteração desejada, logo deve funcionar: // populei um ComboBox para selecionar a impressora e inicializei com a Default begin ... ComboBox1.Items.Assign(Printer.Printers); // Popula lista de impressoras ComboBox1.ItemIndex := Printer.PrinterIndex; // Inicializa com default ... end; ... // no exemplo, ao clicar num botão... begin ... Printer.PrinterIndex := ComboBox1.ItemIndex; // troca a impressora padrão para o TPrinter PrintDialog1.Execute; // Aqui será exibida a caixa de diálogo da impressora selecionada ... end; []s
-
Neste link(http://www.swissdelphicenter.ch/torry/showcode.php?id=266) tem duas rotinas para finalizar processos. Talvez uma lhe sirva, já que você utiliza WinExec. Porém, o help do Delphi diz o seguinte sobre WinExec: This function is provided for compatibility with earlier versions of Windows. For Win32-based applications, use the CreateProcess function. Acho esta opção particularmente interessante porque, se for um processo iniciado por sua aplicação, você terá como terminar especificamente ela. No exemplo abaixo, utilizei um form com um botão para iniciar o processo(programa) e outro para encerrá-lo. Funcionou legal, porém, não sei se é a solução ideal em virtude de algumas possíveis restrições colocadas pelo uso de TerminateProcess (vide help). Talvez algum colega possa fazer alguma colocação a respeito. Também fiquei intrigado pelo fato de não funcionar ao utilizar, na função CreateProcess, o parâmetro nome do módulo(com o programa) e linha de comando(com o arquivo texto) - inicia o notepad mas não abre o arquivo, obrigando a utilizar apenas linha de comando. var ProcessInformation :TProcessInformation; procedure TForm1.btnStartClick(Sender: TObject); var StartupInfo :TStartupInfo; begin FillChar(StartupInfo, SizeOf(StartupInfo), 0); FillChar(ProcessInformation, SizeOf(ProcessInformation), 0); StartupInfo.cb := SizeOf(StartupInfo); StartupInfo.dwFlags := STARTF_USESHOWWINDOW; StartupInfo.wShowWindow := SW_SHOWNORMAL; btnStop.Enabled := CreateProcess(nil, // Nome do módulo executável 'c:\windows\notepad.exe c:\temp\teste.txt', // Linha de comando nil, // Atributos do processo (SECURITY_ATTRIBUTES) nil, // Atributos da thread (SECURITY_ATTRIBUTES) False, // Herdar handles do processo chamador CREATE_NEW_CONSOLE or // Flags de criação e NORMAL_PRIORITY_CLASS, // de prioridade nil, // Variáveis de ambientes para o processo nil, // Diretório corrente do processo StartupInfo, // Determina como a janela do processo deve aparecer ProcessInformation); // Informações sobre o processo criado btnStart.Enabled := not btnStop.Enabled; end; procedure TForm1.btnStopClick(Sender: TObject); begin btnStop.Enabled := False; btnStart.Enabled := not btnStop.Enabled; if not TerminateProcess(ProcessInformation.hProcess, 0) then ShowMessage('O processo já foi encerrado pelo usuário!'); end;
-
Isto posto, estou supondo que não faltou nada mesmo. Também suponho que você tenha utilizado o QuickReport. Então, como disse antes, clique no componente quickreport que você adicionou ao form (normalmente QuickRep1), na janela Object Inspector localize a propriedade DataSet. Se você adicionou ao seu form uma consulta SQL ou uma tabela de onde você deseja obter os dados para o relatório, este é o dataset que você deverá selecionar naquela propriedade. Além disto, observe que a tabela ou query deverá estar aberta quando você for visualizar (testar) seu relatório. Veja se com essas informações você consegue resolver seu problema. Sem saber como você compôs seu relatório fica um pouco difícil dar sugestões. []s
-
Sem problemas. Eu mesmo pensei em iniciar o texto utilizando este termo. Mas como você disse: Funcionou 100% e resolveu a naba; o importante foi solucionar o problema - qualquer hora dessas você acha solução melhor. []s
-
ao que parece você alterou a extensão padrão. Antes abria porque a extensão .html está associado ao navegador padrão. Agora, com .html#id0001 não há nada associado. Acho que há duas alternativas: 1) você coloca o identificador junto ao nome e não à extensão ou; 2) descobre o navegador padrão, e abre o arquivo que você quizer com ele. para a segunda opção é necessário descobrir qual é o navegador padrão, pois podem haver mais que um instalado e ainda você deverá saber aonde. O cógico eu obtive deste link: http://www.delphi.eti.br/downloads.php?id=251 (não alterei nada) // Obtém o programa associado com a extensão function PesquisaPrograma(Ext : string) : string; var Reg: TRegistry; begin Result := ''; Reg := TRegistry.Create; Reg.RootKey := HKEY_CLASSES_ROOT; // chave de sistema if Reg.OpenKey('.' + ext, False) then begin Result := Reg.ReadString(''); Reg.CloseKey; if Result <> '' then begin // pesquisa chave de programa associado if reg.OpenKey(Result + '\Shell\Open\Command', False) then Result := Reg.ReadString(''); Reg.CloseKey; end; end; // tira parâmetros da linha de comando if (Result <> '') and (Pos('%', Result) > 0) then Delete(Result, Pos('%', Result), Length(Result)); if (Result <> '') and (Result[1] = '"') then Delete(Result, 1, 1); if (Result <> '') and (Result[Length(Result)] = '"') then Delete(Result, Length(Result), 1); while (Length(Result) > 0) and ((Result[Length(Result)] = ' ') or (Result[Length(Result)] = '"')) do Delete(Result, Length(Result), 1); end; para o seu caso utilizaria ele da seguinte maneira: var ExePath :string; begin // esta enjambração abaixo, é para que o arquivo possa ser aberto com firefox, // pois no meu caso é o navegador padrão e o string retornado contém um // parâmetro -url e com isso o seu (nosso) arquivo não é mostrado. ExePath := PesquisaPrograma('html'); Delete(ExePath, Pos('.EXE', UpperCase(ExePath)) +4, Length(ExePath)); ShellExecute(Handle, 'open', PChar(ExePathe), 'c:\teste.html#id0001', nil, SW_SHOWNORMAL); []s
-
Na net você encontra muito material (apostilas, tutoriais, exmplos) Mais básico: http://www.apostilando.com/download.php?co...ategoria=Delphi Mais avançado: http://www.apostilando.com/download.php?co...ategoria=Delphi Já neste site, após cadastrar-se, você pode fazer download de diversos programas exemplos (cadastro de funcionários, controle bancário, etc) - na seção de Download. Devem ajudá-lo com suas dúvidas iniciais.
-
provavelmente faltou ligar a propriedade DataSet do TQuickRep1 à sua tabela ou query.
-
parece que não deve nem ter compilado, já que supostamente valor1 é um Float e dbedit.text é um String. Supondo que seja isto, vc poderia fazer: dbedit.text := query.fieldbyname('valor').AsString; ou atribuir o resultado em query.fieldbyname('valor') para o campo(Field) ligado ao seu DBEdit (algo tipo: TabaInicializarVALOR.AsFloat = query.fieldbyname('valor').AsFloat).
-
Já me intrometendo, uma vez que você altera as propriedades do canvas momentos antes do redesenho do grid, se você substituir o código: DBGridInf.Canvas.FillRect(Rect); DBGridInf.Canvas.TextOut(Rect.Left+2,Rect.Top,Column.Field.AsString); por: DBGridInf.DefaultDrawColumnCell(Rect, DataCol, Column, State); não resolve o seu problema, já que o redesenho é executado com suas configurações de cores?
-
Adicione um GroupFooter ao seu relatório e nele utilize 2 QRExpr para realizar o SUM dos campos desejados. No GroupHeader configure a propriedade FooterBand para apontar para o groupfooter recém adicionado. Acho que é isso. []s
-
Isto só é verdade porque, como eu disse antes, o meu exemplo é meio idiota. Se o buffer tivesse muitos registros NÂO apenas 2 (dois) e estivessemos varrendo o buffer num loop, ao final o ponteiro (indexador) estaria apontando para o último registro, ou seja, final da memória alocada (posição 3, 100, 1000 - sei lá) e não na inicial.
-
Observe que na forma de utilização proposta (indexador), a cada incremento, o endereço se modifica. Se não for mantido o endereço inicial do buffer alocado, ao final, você não conseguirá liberar corretamente esta área de memória, visto que este será o endereço que você passará para o Freemem. falou?! O exemplo é meio idiota, eu sei, mas o objetivo é mostrar que pode-se utilizar ponteiros para "navegar" através de uma área de memória. Pode ser útil ao utilizar Stream para ler conteúdo de um arquivo que contenha registros ou similares e você leia blocos grandes de dados para o buffer do Stream. Utilizei isto quando resolvi criar uma classe descendente de TFileStream que implementasse o Writeln e Readln.
-
Negrido Em Algumas Palavras Do Grid
pergunta respondeu ao Vivendo&Aprendendo de Micheus em Delphi, Kylix
Bom, o grosso do serviço tá aqui, já que pode ser melhorado: // Procedimento genérico - pode ser colocado em uma unit para reaproveitamento procedure DrawBold(Canvas :TCanvas; Rect :TRect; Text :string; StrBold :array of string); var Idx, IdxPos :Integer; SubStr :string; begin Idx := 0; Inc(Rect.Left, 2); while Idx < High(StrBold) do begin IdxPos := Pos(StrBold[Idx], Text); case IdxPos of 0 :; // não encontrou, avança próxima StrBold 1 : begin // trata StrBold na 1ª posição Canvas.Font.Style := Canvas.Font.Style +[fsBold]; SubStr := StrBold[Idx]; Canvas.TextRect(Rect, Rect.Left, Rect.Top+2, SubStr); Inc(Rect.Left, Canvas.Textwidth(SubStr)+1); Delete(Text, 1, Length(SubStr)); end; else // todo o resto begin Canvas.Font.Style := Canvas.Font.Style -[fsBold]; SubStr := Copy(Text, 1, IdxPos -1); Canvas.TextRect(Rect, Rect.Left, Rect.Top+2, SubStr); Inc(Rect.Left, Canvas.Textwidth(SubStr)+1); Delete(Text, 1, IdxPos -1); Continue; end; end; Inc(Idx); end; Canvas.Font.Style := Canvas.Font.Style -[fsBold]; if Text <> '' then // sobrando alguma coisa... Canvas.TextRect(Rect, Rect.Left, Rect.Top+2, Text); end; procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect; DataCol: Integer; Column: TColumn; State: TGridDrawState); begin if Column.FieldName = 'Descricao' then begin if gdSelected in State then begin DBGrid1.Canvas.Brush.Color := clHighLight; DBGrid1.Canvas.Font.Color := clHighLightText; end else begin DBGrid1.Canvas.Brush.Color := clWindow; DBGrid1.Canvas.Font.Color := clWindowText; end; DrawBold(DBGrid1.Canvas, Rect, Column.Field.AsString, ['Serviço', 'Categoria', 'Valor Total', 'Sendo', 'De']); end else DBGrid1.DefaultDrawColumnCell(Rect, DataCol, Column, State); end; pela lógica, no seu DBGrid, você deveria precisar modificar a propriedade DefaultDrawing para False, mas a certa altura observei que sem mudá-la também está funcionando - dê uma olhada. No mesmo DBGrid, crie o evento OnDrawColumnCell e insira o código como acima trocando o FieldName (no meu caso era Descricao). []s -
você terá que criar seu próprio editor de propriedades e registrá-lo via RegisterPropertyEditor. Observando que assim você poderá registrar o editor para a propriedade ListSource apenas do seu componente não afetando outros que possam fazer uso do editor default. Aqui te um tutorial legal, bem esmiuçado: http://www.clubedelphi.net/artigos/Criacao_Componentes2.asp
-
você consegue até apresentar propriedades antes invisíveis, porém o contrário não dá. Veja detalhes no link http://info.borland.com/techpubs/delphi/de...sses.html#19292, procure pelo texto Property overrides and redeclarations
-
Fiquei intrigado com a colocação do s3c, com relação da utilização da contante tipada, pois já utilizei deste artifícil antes. Aqui onde estou, só tenho o velho D3 instalado(o D7 só em casa) e testei a alteração explícita da constante no código (como no exemplo), sendo que não obtive qualquer problema (funciona perfeitamente). A menos que nas versões do Delphi isto não seja mais permitido, talvez seja uma questão de configuração - sei lá. Também, para o exemplo citado, acho que não há necessidade de utilização de tipos intermediários. Uma vez que você saiba o tipo de dados que pretende mover, basta criar um ponteiro para o mesmo. Nesta configuração poderíamos colocar o ex. desta maneira: procedure TForm1.Button1Click(Sender: TObject); Const Fim_do_Mes_12 :Byte = 31; var b32 :^Byte; begin b32 := @Fim_do_Mes_12; b32^ := 32; sendo que b32 será um ponteiro para uma área de memórea que conterá Byte e b32^ apontará para o conteúdo desta área. Como neste caso é byte, você lerá byte. Uma aplicação interessante de ponteiros é quando da utilização de buffers onde são armazenados tipos de dados de tamanhos conhecidos. você pode utilizá-los como indexador para o buffer: procedure qualquer_coisa; type PInfo = ^TInfo; TInfo = record Nome :string[20]; // ** observe tamanho fixo Idade :Byte; Sexo :Byte; end; var StrMsg :String; StrBuf :array[1..512] of char; InfoBuf :Pointer; PtrInfo :PInfo; PtrIdx, PtrEnd :PChar; begin FillChar(StrBuf, SizeOf(StrBuf), #0); // preenche todo o StrBuf com zeros // populando o StrBuf para o teste StrPCopy(@StrBuf, 'Testando o uso de ponteiros.'#13'Com quebra de texto.'); StrMsg := ''; PtrIdx := @StrBuf; // início da área de memória PtrEnd := PtrIdx +SizeOf(StrBuf); // Final - máximo esperado while PtrIdx <= PtrEnd do begin case PtrIdx^ of #0 : Break; // caso o StrBuf não tenha sido preenchido totalmente haverão zeros #13 : StrMsg := StrMsg + #10'Nova linha: '; else StrMsg := StrMsg + PtrIdx^; end; Inc(PtrIdx); end; ShowMessage(StrMsg); GetMem(InfoBuf, SizeOf(TInfo) *2); // aloca espaço para dois registros PtrInfo := InfoBuf; // inicializa apontador PtrInfo^.Nome := 'Nome 1'; Inc(PtrInfo); PtrInfo^.Nome := 'Nome 2'; StrMsg := ''; PtrInfo := InfoBuf; StrMsg := 'Nome: '+ PtrInfo^.Nome +#10; Inc(PtrInfo); StrMsg := StrMsg +'Nome: '+ PtrInfo^.Nome; FreeMem(InfoBuf); ShowMessage(StrMsg); end; O indexador será inbrementado automaticamente pelo número de byte que contém a estrutura apontada por ele.
-
Perfeito, entendi. Pelo que o s3c postou, dá mesmo para utilizar o "alter table ... alter column ..." no Paradox. Aprendi mais esta. Apenas mais um comentário, não sei se você já sabe, mas em todos os casos. Se junto com o programinha você não mandar uma versão recompilada do seu programa, com o tamanho (size) dos respectivos fields das tabelas envolvidas na alteração corrigidos, o usuário receberá uma mensagem de erro quando o programa tentar abrir as tabelas (Field '<nome campo>' is not of the expected type.). []s
-
Se bem me lembro, com o Paradox, você deveria modificar na estrutura da tabela - normalmente utilizando Database Desktop. Em outros bancos daria para utilizar instrução SQL "alter table ... alter column ..." Quando você fala "em tempo de execução", sugere que seja algo que você deseja fazer com certa frequência. você poderia esclarecer o que você deseja com este procedimento? Talvez eu tenha entendido a pergunta de forma errada. []s
-
1) Sim. Utilizando o numérico (byte, integer...) 2) Sim. Observando que deverão haver zeros a esquerda completando o número de digitos previstos. 3) Poderia utizar FormatFloat('00', field.AsInteger) - para dois dígitos p.ex.. O melhor evento é o OnExit, já que o OnChange ocorre a cada tecla digitada.
-
Dê uma espiada no help em THintWindow e seu método ActivateHint. Se quizer uma customização simples de seu hint tem uma dica aqui http://www.swissdelphicenter.ch/torry/showcode.php?id=3
-
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.
-
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 como CTRLPressed := (GetAsyncKeyState(VK_CONTROL) and $8000) <> 0; na callback, para que você apenas chame seu aplicativo com a combinação CTRL+F3. []s p.s. valeu pela oportunidade de aprender mais esta.
-
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
-
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).
-
Cabeçalho e rodapé não dá para ajustar no componente; apenas parágrafos, fontes e tabulações. FirstIdent corresponde ao recuo da primeira linha do parágrafo; A formatação é válida para texto inserido após a posição do cursor, onde foi aplicado o formato, ou para o texto selecionado. Assim, para formatar a margem e parágrafo do texto: RE.SelectAll; RE.Paragraph.FirstIndent := <recuo do parágrafo se houver>; RE.Paragraph.LeftIndent := -RE.Paragraph.FirstIndent +NEEsquerda.AsInteger; // necessário para correção da posição RE.Paragraph.RightIndent := NEDireita.AsInteger;