{Frame + background} const WS_EX_LAYERED = $00080000; function SetLayeredWindowAttributes(Hwnd: THandle; crKey: COLORREF; bAlpha: Byte; dwFlags: DWORD): Boolean; stdcall; external user32 name 'SetLayeredWindowAttributes'; const defFrameText = '%artist% - %title%'; const // opt_HiddenByMe:PAnsiChar = 'frame/hiddenbyme'; opt_ShowCtrls :PAnsiChar = 'frame/showcontrols'; opt_FrmUsePic :PAnsiChar = 'frame/frmusepic'; opt_FrmUseCvr :PAnsiChar = 'frame/frmusecover'; opt_FrmBkColor:PAnsiChar = 'frame/frmbkcolor'; opt_FrmBkPic :PAnsiChar = 'frame/frmbkpic'; opt_FrmBkMode :PAnsiChar = 'frame/frmbkmode'; opt_FrmAlpha :PAnsiChar = 'frame/frmalpha'; opt_HideFrameM:PAnsiChar = 'frame/hideframem'; opt_HideFrameP:PAnsiChar = 'frame/hideframep'; opt_FrmTimer :PAnsiChar = 'frame/frametimer'; opt_PadLeft :PAnsiChar = 'frame/paddingleft'; opt_PadTop :PAnsiChar = 'frame/paddingtop'; opt_PadRight :PAnsiChar = 'frame/paddingright'; opt_PadBottom :PAnsiChar = 'frame/paddingbottom'; opt_Manual :PAnsiChar = 'frame/manualplacement'; procedure TWATFrame.ResetFrame; var D:PWATFrameData; begin D:=CustomData; if D.Trackbar <>nil then ResetTrackbar(D.Trackbar); if D.TextBlock<>nil then D.TextBlock.BlockText:=nil; // frame back to default RefreshPicture(nil); end; procedure FrameTimerProc(wnd:HWND;uMsg:uint;idEvent:uint_ptr;dwTime:dword); stdcall; var psi:pSongInfo; D:PWATFrameData; begin D:=FrameCtrl.CustomData; if IsFrameHidden(D.FrameId) then begin if not D.wasHidden then begin D.wasHidden:=true; D.TextBlock.UpdateTime:=0; end; exit; end else if D.wasHidden and (D.TextBlock.UpdateTime=0) then begin D.wasHidden:=false; if (D.ShowControls and scText)<>0 then D.TextBlock.UpdateTime:=DBReadWord(0,PluginShort,opt_TxtTimer,10); end; if D.Trackbar<>nil then begin if (CallService(MS_WAT_GETMUSICINFO,WAT_INF_CHANGES,dword(@psi))<>WAT_PLS_NOTFOUND) then begin SetTrackBarPosition(D.Trackbar,(psi^.time*1000) div D.UpdInterval) end; end; UpdateTextBlock(D,false); // false - check for %percent%/%time% FrameCtrl.Update; end; procedure TWATFrame.AdjustFrame; var h:integer; D:PWATFrameData; begin D:=CustomData; if D.ManualPlacement then begin if D.Trackbar <>nil then D.Trackbar .Anchor(false,false,false,false); if D.TextBlock<>nil then D.TextBlock.Anchor(false,false,false,false); DesignerLoadSettings; exit; end; h:=Height; // or need to get FRAME height if D.Trackbar<>nil then begin D.Trackbar.SetSize(Width-16,18); dec(h,D.Trackbar.Height); D.Trackbar.SetPosition(8,h); D.Trackbar.Anchor(true,false,true,true); end; if (D.ShowControls and scButtons)<>0 then begin AdjustButtons(h-16-BtnGap); dec(h,16+2*BtnGap); end; if D.TextBlock<>nil then begin D.TextBlock.Top :=awkTextPad; D.TextBlock.Height:=h-D.TextBlock.Top; D.TextBlock.Anchor(true,true,true,true); end; end; procedure TWATFrame.SaveSettings; var D:PWATFrameData; begin D:=CustomData; DBWriteByte (0,PluginShort,opt_Manual ,ord(D.ManualPlacement)); DBWriteByte (0,PluginShort,opt_HideFrameM,ord(D.HideNoMusic)); DBWriteByte (0,PluginShort,opt_HideFrameP,ord(D.HideNoPlayer)); DBWriteByte (0,PluginShort,opt_FrmUsePic ,ord(D.UseBkPicture)); DBWriteByte (0,PluginShort,opt_FrmUseCvr ,ord(D.UseCover)); DBWriteDWord (0,PluginShort,opt_FrmBkColor,D.BkColor); DBWriteWord (0,PluginShort,opt_FrmBkMode ,D.BkMode); DBWriteDWord (0,PluginShort,opt_ShowCtrls ,D.ShowControls); DBWriteByte (0,PluginShort,opt_FrmAlpha ,D.FrmAlpha); DBWriteWord (0,PluginShort,opt_FrmTimer ,D.UpdInterval); DBWriteWord (0,PluginShort,opt_PadLeft ,D.padding.left); DBWriteWord (0,PluginShort,opt_PadTop ,D.padding.top); DBWriteWord (0,PluginShort,opt_PadRight ,D.padding.right); DBWriteWord (0,PluginShort,opt_PadBottom ,D.padding.bottom); DBWriteString(0,PluginShort,opt_FrmBkPic ,D.BkDefFile); CheckControls; AdjustFrame; RefreshPicture; InvalidateRect(FrameCtrl.GetWindowHandle,nil,true); FrameCtrl.Update; if D.UpdTimer<>0 then // FrameWnd MUST be present begin KillTimer(0,D.UpdTimer); D.UpdTimer:=0; end; if D.UpdInterval>0 then begin D.UpdTimer:=SetTimer(0,0,D.UpdInterval,@FrameTimerProc); end; end; procedure TWATFrame.LoadSettings; var D:PWATFrameData; begin D:=CustomData; D.ManualPlacement:=DBReadByte (0,PluginShort,opt_Manual ,0)<>0; D.HideNoMusic :=DBReadByte (0,PluginShort,opt_HideFrameM,0)<>0; D.HideNoPlayer :=DBReadByte (0,PluginShort,opt_HideFrameP,0)<>0; D.UseBkPicture :=DBReadByte (0,PluginShort,opt_FrmUsePic ,0)<>0; D.UseCover :=DBReadByte (0,PluginShort,opt_FrmUseCvr ,0)<>0; D.BkColor :=DBReadDWord(0,PluginShort,opt_FrmBkColor,$00E0E0E0); D.BkMode :=DBReadWord (0,PluginShort,opt_FrmBkMode ,frbkCenter); D.ShowControls :=DBReadDWord(0,PluginShort,opt_ShowCtrls ,scAll); D.FrmAlpha :=DBReadByte (0,PluginShort,opt_FrmAlpha ,255); D.UpdInterval:=DBReadWord(0,PluginShort,opt_FrmTimer,200); if D.UpdInterval<100 then D.UpdInterval:=D.UpdInterval*1000; D.padding.left :=DBReadWord(0,PluginShort,opt_PadLeft ,0); D.padding.top :=DBReadWord(0,PluginShort,opt_PadTop ,0); D.padding.right :=DBReadWord(0,PluginShort,opt_PadRight ,0); D.padding.bottom:=DBReadWord(0,PluginShort,opt_PadBottom,0); D.BkDefFile:=DBReadString(0,PluginShort,opt_FrmBkPic,nil); //!!!! saving NOT in TextBlock D.Template:=DBReadUnicode(0,PluginShort,opt_FrameText,DefFrameText); end; {$include i_bitmap.inc} procedure TWATFrame.SetAlpha(value:integer); const LWA_COLORKEY = $00000001; LWA_ALPHA = $00000002; var wnd:HWND; x:cardinal; begin if IsFrameFloated(PWATFrameData(CustomData).FrameId) then begin wnd:=GetParent(FrameCtrl.GetWindowHandle); x:=GetWindowLongW(wnd,GWL_EXSTYLE); if value<>255 then begin if (x and WS_EX_LAYERED)=0 then SetWindowLongW(wnd,GWL_EXSTYLE,x or WS_EX_LAYERED); SetLayeredWindowAttributes(wnd,0,value,LWA_ALPHA); end else if (x and WS_EX_LAYERED)<>0 then SetWindowLongW(wnd,GWL_EXSTYLE,x and not WS_EX_LAYERED); end; end; procedure TWATFrame.FrameResize(Sender: PObj); var tmpBmp:HBITMAP; D:PWATFrameData; begin D:=CustomData; if D.BkDC<>0 then begin tmpBmp:=GetCurrentObject(D.BkDC,OBJ_BITMAP); DeleteDC(D.BkDC); D.BkDC:=0; DeleteObject(tmpBmp); end; AdjustFrame; end; procedure BkTimerProc(wnd:HWND;uMsg:uint;idEvent:uint_ptr;dwTime:dword); stdcall; var D:PWATFrameData; begin D:=FrameCtrl.CustomData; KillTimer(0,D.BkTimer); D.BkTimer:=0; DeleteObject(D.BkBitmap); D.BkBitmap:=0; end; procedure TWATFrame.RefreshPicture(cover:PAnsiChar=nil); var D:PWATFrameData; begin D:=CustomData; if D.BkBitmap<>0 then BkTimerProc(0,0,0,0); // remove old picture FrameResize(nil); // clear frame bitmap buffer if D.UseBkPicture then D.BkBitmap:=LoadBkPicture(cover,true,D.BkDefFile); if D.BkBitmap=HBITMAP(-1) then // same file D.BkBitmap:=0; Update; end; procedure TWATFrame.Paint(Sender: PControl; DC: HDC); var rc: TRect; br:HBRUSH; D:PWATFrameData; begin D:=CustomData; GetClientRect(Sender.Handle,rc); if D.UseBkPicture then begin if D.BkDC=0 then begin if D.BkBitmap=0 then begin if (D.BkFile<>nil) and (D.BkFile^<>#0) then D.BkBitmap:=CallService(MS_UTILS_LOADBITMAP,0,dword(D.BkFile)); end; if D.BkBitmap<>0 then begin PreparePicture(dc,rc); D.BkTimer:=SetTimer(0,0,10000,@BkTimerProc); end; end; if D.BkDC<>0 then begin BitBlt(dc,rc.left,rc.top,rc.right-rc.left,rc.bottom-rc.top, D.BkDC,rc.left,rc.top,SRCCOPY); exit; end; end; InflateRect(rc,1,1); br:=CreateSolidBrush(D.BkColor); FillRect(dc,rc,br); DeleteObject(br); end; // JUST LOAD picture, no matter, which transforms // Backname = from settings, Covername = from data (higher priority) // -1 - same file, 0 - can't load, other - new bitmap function TWATFrame.LoadBkPicture(CoverFName:PAnsiChar;check:boolean=false; BackFName:PAnsiChar=nil):integer; var tmpstr:PAnsiChar; D:PWATFrameData; begin result:=0; D:=CustomData; // check the same file, ie only 'next pic' if (CoverFName<>nil) and (CoverFName^<>#0) then begin if check and (StrCmp(CoverFName,D.BkFile)=0) then begin result:=-1; Exit; end; result:=CallService(MS_UTILS_LOADBITMAP,0,dword(CoverFName)); if result<>0 then begin mFreeMem(D.BkFile); StrDup(D.BkFile,CoverFName); Exit; end; end; if (BackFName<>nil) and (BackFName^<>#0) then begin tmpstr:=ParseVarString(BackFName); if (tmpstr<>nil) and (tmpstr^<>#0) then begin if (not check) or (StrCmp(tmpstr,D.BkFile)<>0) then begin result:=CallService(MS_UTILS_LOADBITMAP,0,dword(tmpstr)); if result<>0 then begin mFreeMem(D.BkFile); StrDup(D.BkFile,tmpstr); end; end else result:=-1; end; mFreeMem(tmpstr); end; end; procedure TWATFrame.ClearBitmapData; var D:PWATFrameData; tmpBmp:HBITMAP; begin D:=CustomData; if D.BkTimer<>0 then begin KillTimer(0,D.BkTimer); D.BkTimer:=0; end; if D.BkDC<>0 then begin tmpBmp:=GetCurrentObject(D.BkDC,OBJ_BITMAP); DeleteDC(D.BkDC); D.BkDC:=0; DeleteObject(tmpBmp); end; if D.BkBitmap<>0 then begin DeleteObject(D.BkBitmap); D.BkBitmap:=0; end; mFreeMem(D.BkFile); end; procedure TWATFrame.MyDestroy(sender:PObj); var D:PWATFrameData; begin D:=CustomData; if D.UpdTimer<>0 then begin KillTimer(0,D.UpdTimer); D.UpdTimer:=0; end; mFreeMem(D.Template); mFreeMem(D.BkDefFile); ClearBitmapData; if D.Designer<>nil then begin D.Designer.Free; D.Designer:=nil; end; end; procedure TWATFrame.RefreshAllFrameIcons; var D:PWATFrameData; begin D:=CustomData; if (D.ShowControls and scButtons)<>0 then RefreshButtonIcons; if D.Trackbar<>nil then RefreshTrackbarIcons(D.Trackbar); end; procedure TWATFrame.CheckControls; var D:PWATFrameData; psi:pSongInfo; begin D:=CustomData; if (D.ShowControls and scTrackBar)<>0 then begin if D.Trackbar=nil then begin RegisterButtonIcons; D.Trackbar:=MakeNewTrackbar(@self); // for case when TB creating after track start (fastest way) // can use (CallService(MS_WAT_GETMUSICINFO,WAT_INF_CHANGES,dword(@psi))<>WAT_PLS_NOTFOUND) psi:=pointer(CallService(MS_WAT_RETURNGLOBAL,WAT_INF_UNICODE,1)); TrackbarSetRange(D.Trackbar,D.UpdInterval,psi^.total); end; end else if D.Trackbar<>nil then begin D.Trackbar.Free; D.Trackbar:=nil; end; if (D.ShowControls and scButtons)<>0 then begin if D.btnarray[0]=nil then begin if RegisterButtonIcons then MakeNewButtonGroup; end end else if D.btnarray[0]<>nil then FreeButtons; { if (D.ShowControls and scText)<>0 then begin } if D.TextBlock=nil then begin D.TextBlock:=MakeTextBlock(@self,D.BkColor); end; if (D.ShowControls and scText)<>0 then D.TextBlock.UpdateTime:=DBReadWord(0,PluginShort,opt_TxtTimer,10); { end else if D.TextBlock<>nil then begin D.TextBlock.Free; D.TextBlock:=nil; end; } if D.UseBkPicture then begin D.BkBitmap:=LoadBkPicture(nil,true,D.BkDefFile); if D.BkBitmap=HBITMAP(-1) then D.BkBitmap:=0; end else ClearBitmapData; end; function CreateFrameWindow(parent:HWND):THANDLE; var D:PWATFrameData; begin result:=0; FrameCtrl:=PWATFrame(NewAlienPanel(parent,esNone)); if FrameCtrl<>nil then begin GetMem (D ,SizeOf(TWATFrameData)); FillChar(D^,SizeOf(TWATFrameData),0); // clear all including buttons with FrameCtrl^ do begin CustomData:=D; LoadSettings; result:=GetWindowHandle; CheckControls; MinWidth :=80; MinHeight:=30; OnPaint :=FrameCtrl.Paint; OnResize :=FrameCtrl.FrameResize; // OnMouseDown :=TOnMouse(MakeMethod(nil, @MouseDown)); OnMouseDblClk:=FrameCtrl.CreateDesigner; end; FrameCtrl.OnDestroy:=FrameCtrl.MyDestroy; // theoretically, must get Resize here.... or after // FrameCtrl.AdjustFrame; end; end;