我们可以像这样在编译时覆盖特定消息的处理程序:
SELECT
invoice_month,
time_of_month,
ARRAY_AGG(id) invoice_ids
FROM (
SELECT
id,
invoice_month,
-- Categorize as end or beginning of month
CASE
WHEN month_rank <= 10 THEN 'beginning'
WHEN month_reverse_rank <= 10 THEN 'end'
ELSE 'bug' -- Should never happen. Just a fall back in case of a bug.
END AS time_of_month
FROM (
SELECT
id,
invoice_month,
dense_rank() OVER (PARTITION BY invoice_month ORDER BY invoice_date) month_rank,
dense_rank() OVER (PARTITION BY invoice_month ORDER BY invoice_date DESC) month_rank_reverse
FROM (
SELECT
id,
invoice_date,
to_char(invoice_date, 'Mon-yy') AS invoice_month
FROM public.invoice
WHERE invoice_date BETWEEN date '2017-10-01' AND date '2018-09-30'
) AS fiscal_year_invoices
) ranked_invoices
-- Get first and last 10
WHERE month_rank <= 10 OR month_reverse_rank <= 10
) first_and_last_by_month
GROUP BY
invoice_month,
time_of_month
是否可以在不使用message关键字声明方法的情况下动态创建消息处理程序?
答案 0 :(得分:-1)
没有内置的语法构造可动态覆盖消息处理程序。但是,有许多方法可以实现相同的行为。正如David所建议的那样,您可以覆盖WndProc
并在那里处理。否则,您也可以这样做:
type
{ Return false to call inherited handler }
TConditionalHandler = reference to function(var msg : TMessage) : boolean;
TForm1 = class(TForm)
private
FDoOnPaint : TConditionalHandler;
procedure DoOnPaint(var msg : TMessage); message WM_PAINT;
end;
其中(例如)
procedure TForm1.DoOnPaint(var msg: TMessage);
begin
if Assigned(FDoOnPaint) then begin
{ Allow handler to choose if inherited is called... }
if not FDoOnPaint(msg) then inherited;
end else
inherited;
end;
允许您动态附加处理程序
if not Assigned(FDoOnPaint) then begin
FDoOnPaint := function(var msg : TMessage) : boolean
begin
self.Caption := DateTimeToStr(Now);
result := false; { Not actually doing any painting... call inherited }
end;