delphi 在Firemonkey应用程序中接收Windows消息时遇到问题,例如MM_WOM_DONE

44u64gxh  于 2024-01-07  发布在  Windows
关注(0)|答案(1)|浏览(299)

我正在尝试将一个工作的VCL示例翻译到Firemonkey,但无法获得MM_WOM_DONE消息超过一天。如何修复“完成”过程以在Firemonkey中接收MM_WOM_DONE?
P.S.在我的真实的应用程序中,我需要构建音频样本真实的时间,因此发送缓冲区到音频播放是至关重要的,这是我发现的唯一适合我的例子。如果有人有任何低延迟的FMX工作的例子,我会很感激。

  1. unit Unit1;
  2. interface
  3. uses
  4. System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  5. FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
  6. FMX.Controls.Presentation, FMX.StdCtrls, waveio, MMSystem, Windows, Messaging, FMX.Platform.Win;
  7. const
  8. BUFFER_LENGTH = 100;
  9. NUM_BUFFERS = 8;
  10. GRAPH_WIDTH = 200;
  11. type
  12. TFormMain = class(TForm)
  13. button1: TButton;
  14. procedure button1Click(Sender: TObject);
  15. private
  16. { Private declarations }
  17. ws: TFileWaveStream;
  18. PCMReader: TPCMWaveReader;
  19. Headers: array [0..NUM_BUFFERS-1] of TWaveHdr;
  20. BufferLength: Longint;
  21. CurrentBuffer, Ending: Integer;
  22. waveout: HWaveOut;
  23. Graphic: array [0..GRAPH_WIDTH-1, 0..1] of Byte;
  24. Closing: Boolean;
  25. procedure OpenFile( FileName: String );
  26. procedure CloseFile;
  27. procedure WriteBuffer;
  28. procedure Done( var Msg: TMessage ); message MM_WOM_DONE;
  29. public
  30. { Public declarations }
  31. end;
  32. var
  33. FormMain: TFormMain;
  34. implementation
  35. {$R *.fmx}
  36. procedure TFormMain.OpenFile( FileName: String );
  37. var
  38. Cnt: Integer;
  39. begin
  40. ws := TFileWaveStream.Create( FileName, nil );
  41. PCMReader := TPCMWaveReader.Create( ws );
  42. CurrentBuffer := 0;
  43. Ending := 1;
  44. Closing := False;
  45. BufferLength := ((PCMReader.Format^.nAvgBytesPerSec * BUFFER_LENGTH)
  46. div (1000 * PCMReader.Format^.nBlockAlign)) * PCMReader.Format^.nBlockAlign;
  47. if (PCMReader.Size > 0) then
  48. begin
  49. waveOutOpen( @waveout, WAVE_MAPPER, PCMReader.Format, WindowHandleToPlatform(Self.Handle).Wnd,
  50. Integer(self), CALLBACK_WINDOW or WAVE_ALLOWSYNC );
  51. for Cnt := 0 to NUM_BUFFERS-1 do
  52. begin
  53. ZeroMemory(@Headers[Cnt], sizeof(Headers[Cnt]));
  54. with Headers[Cnt] do
  55. begin
  56. GetMem( lpData, BufferLength );
  57. dwBufferLength := BufferLength;
  58. dwFlags := WHDR_DONE;
  59. end;
  60. waveOutPrepareHeader( waveout, @(Headers[Cnt]), sizeof(Headers[Cnt]) );
  61. end;
  62. for Cnt := 0 to NUM_BUFFERS-1 do
  63. WriteBuffer;
  64. end;
  65. end;
  66. procedure TFormMain.CloseFile;
  67. var
  68. Cnt: Integer;
  69. p: Pointer;
  70. begin
  71. if (waveout <> 0) then
  72. begin
  73. Closing := True;
  74. waveOutReset( waveout );
  75. for Cnt := 0 to NUM_BUFFERS-1 do
  76. begin
  77. p := Headers[Cnt].lpData;
  78. waveOutUnprepareHeader( waveout, @Headers[Cnt], sizeof(Headers[Cnt]) );
  79. FreeMem( p );
  80. end;
  81. waveOutClose( waveout );
  82. waveout := 0;
  83. end;
  84. if (PCMReader <> nil) then
  85. PCMReader.Free;
  86. PCMReader := nil;
  87. if (ws <> nil) then
  88. ws.Free;
  89. ws := nil;
  90. end;
  91. procedure TFormMain.WriteBuffer;
  92. var
  93. sw: Integer;
  94. begin
  95. if (Closing) then exit;
  96. sw := PCMReader.Read( Headers[CurrentBuffer].lpData^,
  97. BufferLength div PCMReader.Format^.nBlockAlign )
  98. * PCMReader.Format^.nBlockAlign;
  99. if (sw > 0) then
  100. begin
  101. if BufferLength <> sw then
  102. if PCMReader.Format^.wBitsPerSample = 8 then
  103. FillMemory( PChar(Headers[CurrentBuffer].lpData) + sw,
  104. BufferLength - sw, 128 )
  105. else
  106. ZeroMemory( PChar(Headers[CurrentBuffer].lpData) + sw,
  107. BufferLength - sw );
  108. waveOutWrite( waveout, @Headers[CurrentBuffer],
  109. sizeof(Headers[CurrentBuffer]) );
  110. end
  111. else
  112. if (Ending < NUM_BUFFERS) then
  113. Inc( Ending );
  114. //else
  115. // PostMessage( WindowHandleToPlatform(Self.Handle).Wnd, WM_USER, 0, 0 );
  116. CurrentBuffer := (CurrentBuffer + 1) mod NUM_BUFFERS;
  117. end;
  118. procedure TFormMain.Done( var Msg: TMessage );
  119. begin
  120. WriteBuffer;
  121. end;
  122. procedure TFormMain.button1Click(Sender: TObject);
  123. begin
  124. CloseFile;
  125. OpenFile( 'C:\Users\M\Documents\Rhodes C notest.wav' );
  126. end;
  127. end.

字符串
我尝试通过Windows API打开一个不可见的窗口,只是为了能够使MM_WOM_DONE成为可能。我不能使它工作,但这可能是由于我缺乏知识,这是如何在最近版本的 Delphi 。

soat7uwm

soat7uwm1#

与VCL不同,FireMonkey * 不会 * 将未处理的窗口消息发送到虚拟WndProc方法或message处理程序。它只在内部处理它想要的少数消息,然后丢弃其余消息。
因此,您将不得不直接使用SetWindowLongPtr(GWL_WNDPROC)SetWindowSubClass()手动子类化TForm的Win32 HWND,以便捕获任何您想要的额外消息。
参见How detect the mouse back and forward buttons in a Delphi FMX Windows form?以获取此类子类的示例。

相关问题