程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> Delphi >> [Delphi版]羅技無限靈貂,驅動程序補丁-實現真正的多媒體播放器

[Delphi版]羅技無限靈貂,驅動程序補丁-實現真正的多媒體播放器

編輯:Delphi

  [Delphi版]羅技無限靈貂,驅動程序補丁-實現真正的多媒體播放器!附QQ圖標偽裝程序
   
   
  ██████████ QQ圖標偽裝程序
   
      將 QQ 聊天窗口的標題欄中的 “與 某某 聊天” 變成 “我的文檔 某某”,而且聊天窗口的圖標變成 Word 文檔的圖標,托盤中的圖標在不同狀態時也變成其它圖標:例如在線=網絡驅動器、離開=軟盤驅動器、隱身=硬盤驅動器、離線=斷開網絡驅動器。
   
      變圖標不需要編程,修改 QQ2004 的 QQRes.Dll 文件即可。
   
   
  ██████████ 羅技無限靈貂,驅動程序補丁-實現真正的多媒體播放器
   
      羅技無限靈貂是羅技公司推出的一款多功能無線鼠標,英文名稱叫做“Logitech Media Player”,顧名思義-多媒體遙控器。
   
      該款鼠標最大的特色就是嵌入了眾多的功能鍵,除滾輪外,另有8個鍵。其中側面的兩個鍵在羅技眾多的中高檔鼠標都已配備,功能主要是上下浏覽;頂部的六個鍵組成多媒體鍵區,包括:“Media、Play/Pause、Forward、Backward、+、-”。此外,滾輪可進行十字導航,即多了左右浏覽功能。
   
      但在實際使用中,多媒體鍵的功能實在有限,以我的標准看來,根本發揮不了遙控器的作用!為什麼這麼說呢?
   
      我鐘愛使用的媒體播放器是MPC(MS Windows Media Player Classic),它短小精悍、啟動快、占資源少、快捷鍵豐富,用鼠標、鍵盤操作起來十分簡單。
   
      下面針對 MPC 說說靈貂的缺憾:
      播放/暫停 點擊左鍵或 Space 即可,左鍵就在鼠標上,因此 Play/Pause 鍵就多余了;
      下一個/上一個 點擊 PgUp/PgDown 即可,雖然鼠標上對應的是 Forward/Backward,但我們在看一個電影或者視頻片斷的時候,有多少機會能在中途去看上一個或者下一個文件呢?即使針對超過10分鐘的視頻文件,看完一個,手工去點擊下一個文件也不是很費事的工作麼,因此這兩個鍵也就多余了。
   
      羅技提供的最新驅動程序並未提供上述三個鍵的自定義功能,因此為了充分地利用上鼠標上的眾多功能鍵,我只好在 QQ 圖標程序中加入了新的代碼來實現這三個鍵的自定義功能,並且還可以在不同的應用程序中令同一個鼠標鍵實現不同的自定義功能。
   
      利用官方的驅動設置程序設置:
      Media 鍵的功能為組合鍵:Ctrl+F4,縮放的功能為關閉程序(效率十分高)。
   
      之後的程序可以實現如下功能(主要是組合鍵):
   
      ◎MPC
      向上浏覽:前進10秒;向下浏覽:倒退10秒。
      ◎ACDSee
      Play/Pause:Ctrl+Del;Forward:Alt+C;Backward:Alt+M。
      ◎ACD FotoCanvas
      Play/Pause:Ctrl+S;Forward:Shift+A;Backward:Shift+S。
      ◎NetCaptor
      Play/Pause:Ctrl+Shift+S;Foward:F3;Backward:F2。
      ◎UltraEdit
      Play/Pause:Ctrl+S;Foward:Ctrl+Shift+F6;Backward:Ctrl+F6。
     
      最後我要鄙視一下羅技無限靈貂驅動程序的開發人員!
      鼠標驅動的核心功能在於對鼠標傳來的位移信號的換算與處理,還有諸如各種按鍵的定義、加速度的處理等問題,但這些相對於移動信號的處理與分析來說只是小問題,在這一方面的程序編制並不存在功能上的技術困難。既然你們作出了那麼多中高檔的鼠標,尤其是我花了360人民幣買的這款靈貂,為何不再多敲些代碼,把多媒體鍵區的幾個鍵也加入自定義功能。畢竟計算機不是電視、錄音機、VCD機、DVD機、組合音響…,多媒體功能只是計算機的一部分功能,多數人還是要用它來做其它很多游泳的事情的,如果能在更多的應用軟件中讓每個鍵都實現自定義功能,那麼以它目前不到400元的價格和為數眾多的鼠標鍵,絕對是一款超值的鼠標!
   
   
  ██████████ Delphi 代碼如下,其中只有MPC用到了鉤子,因為在媒體播放軟件中,多媒體鍵區的鍵及兩個側鍵產生的消息都被羅技的驅動鉤子給拐跑了,所以要自己編個全局鉤子提前把消息攔住,讓羅技的鉤子鉤不到我需要的消息。
   
   
  //▓▓▓▓▓▓▓▓▓ ReTitle.dpr
  program ReTitle;

  uses
    Forms,
    SysUtils,
    Windows,
    Unit1 in 'Unit1.pas' {f},
    DlgDebug_U in 'DlgDebug_U.pas' {dlgDebug};

  {$R *.res}

  begin
    Application.Initialize;

  //調試狀態
  dbg := findCmdLineSwitch('debug', ['/', '-'], true);
  if dbg then  with dlgDebug do begin
   dlgDebug := TDlgDebug.Create(Application);  Show;
   Left := GetSystemMetrics(SM_CXSCREEN)-Width ;
      Top  := GetSystemMetrics(SM_CYSCREEN)-Height-60;
  end;

    Application.CreateForm(Tf, f);
    Application.Run;
  end.
   
   
  //▓▓▓▓▓▓▓▓▓ Unit1.pas
  unit Unit1;

  interface

  uses
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
    Dialogs, StdCtrls, ExtCtrls, DlgDebug_U;

  type
    Tf = class(TForm)
      Tmr: TTimer;
      procedure FormCreate(Sender: TObject);
      procedure TmrTimer(Sender: TObject);
      procedure WndProc(var Message: TMessage); override;
    private
      { Private declarations }
      hFocus: HWND;
      Buf: array[0..1024] of Char;
      sTitle: string;
      //QQ
      procedure GetMousePosHwndAndClassName(Sender : TPoint);
      function replacing(s,source,target:string):string;
      //羅技無限靈貂
      procedure Down(VK: byte);
      procedure UP  (VK: byte);
      procedure Key1(VK1          : byte);
      procedure Key2(VK1, VK2     : byte);
      procedure Key3(VK1, VK2, VK3: byte);
    public
      { Public declarations }
    end;

  var
    f: Tf;

  const
      LOGITECH   = $0319;
      PLAY_PAUSE = $E0000;
      PLAY_LEFT  = $C0000;
      PLAY_RIGHT = $B0000;

     
  implementation
      procedure EnableWheelHook ; stdcall; external 'HookPrj.dll';
      procedure DisableWheelHook; stdcall; external 'HookPrj.dll';
  {$R *.dfm}

  procedure Tf.FormCreate(Sender: TObject);//█████████████ 界面初始化
  begin
      FormStyle := fsStayOnTop;
      Height:=0;
      Width:=0;
      Hide;
     
      Tmr.Interval := 50;
     
      ShowWindow(Application.Handle, SW_HIDE);
      SetWindowLong(Application.Handle, GWL_EXSTYLE,
          GetWindowLong(Application.handle, GWL_EXSTYLE) or WS_EX_TOOLWINDOW AND NOT WS_EX_APPWINDOW);

      EnableWheelHook;//羅技靈貂藍色側鍵,WM_MouseWheel 消息鉤子
  end;

  procedure Tf.GetMousePosHwndAndClassName(Sender: TPoint);//███ 偽裝標題欄
  var hWnd: THandle;
      aTitle: array [0..255] of char;
      str:string;
  begin
      hWnd := WindowFromPoint(Sender);

      if boolean(GetWindowText(hWnd, aTitle, 256)) then begin
          str :=  string(aTitle);

          //QQ
          if ((pos('與',str)>0) and (pos('聊天中',str)>0)) then begin
              str:=replacing(str, ' 聊天中', '');
              str:=replacing(str, '與', '我的文檔');
              SetWindowText(hWnd,pchar(str));
          end;

          if ((pos('群 -',str)>0) or (pos('高級群 -',str)>0)) then begin
              str:=replacing(str, '群 -', '我的信件');
              str:=replacing(str, '高級', '');
              SetWindowText(hWnd,pchar(str));
          end;

          //聊天室
          if pos('QQ 聊天室', str)>0 then begin
              str := 'Microsoft Visual C++ 6.2';
              SetWindowText(hWnd,pchar(str));
          end;

          //MSN
          if pos(' - 對話', str)>0 then begin
              str := replacing(str, ' - 對話', '工作文檔');
              SetWindowText(hWnd,pchar(str));
          end;
      end;
  end;

  procedure Tf.TmrTimer(Sender: TObject);//████████████▌定時器
  var rPos: TPoint;
  begin
      if boolean(GetCursorPos(rPos)) then GetMousePosHwndAndClassName(rPos);
  end;

  function Tf.replacing(s,source,target:string):string;//█████ 替換字符串
  var site, strlen: integer;
  begin
      site:=pos(source,s);
      strlen:=length(source);
      delete(s,site,strlen);
      insert(target,s,site);
      result:=s;
  end;

  procedure Tf.WndProc(var Message: TMessage);////███████▌羅技無限靈貂
  begin with Message do begin
      inherited;

      //如果不是多媒體鍵區的中右側三個鍵按下,則退出
      IF NOT(  (Msg=LOGITECH) and ((lParam=PLAY_PAUSE)or(lParam=PLAY_LEFT)or(lParam=PLAY_RIGHT))  ) THEN exit;

      hFocus := GetForegroundWindow;
      GetWindowText(hFocus, buf, 1024);
      sTitle := string(buf);
      deb(sTitle);

      //ACDSee
      if (pos('ACDSee', sTitle)>0) and (pos('5.0', sTitle)>0) and (Msg=LOGITECH) then case lParam of
          PLAY_PAUSE: Key2(VK_Control, VK_Delete);//Ctrl+Del
          PLAY_LEFT : Key2(VK_Menu   , ord('M') );//Alt+M
          PLAY_RIGHT: Key2(VK_Menu   , Ord('C') );//Alt+C
      end;

      if (pos('ACD', sTitle)>0) and (pos('FotoCanvas', sTitle)>0) and (Msg=LOGITECH) then case lParam of
          PLAY_PAUSE: Key2(VK_Control, ord('S'));//Ctrl+S
          PLAY_LEFT : Key2(VK_Shift  , ord('S'));//Shift+S
          PLAY_RIGHT: Key2(VK_Shift  , Ord('A'));//Shift+A
      end;

      //NetCaptor
      if (pos('NetCaptor', sTitle)>0) and (Msg=LOGITECH) then case lParam of
          PLAY_PAUSE: Key3(VK_Control, VK_Shift, ord('S'));//Ctrl+Shift+S
          PLAY_LEFT : Key1(VK_F2);
          PLAY_RIGHT: Key1(VK_F3);
      end;

      //UltraEdit
      if (pos('UltraEdit-32', sTitle)>0) and (Msg=LOGITECH) then case lParam of
          PLAY_PAUSE: Key2(VK_Control, ord('S'));//Ctrl+S
          PLAY_LEFT : Key2(VK_Control, VK_F6   );//Ctrl+F6
          PLAY_RIGHT: Key3(VK_Control, VK_Shift, VK_F6);//Ctrl+Shift+F6
      end;

  end; end;

  procedure Tf.Down(VK: byte); begin keybd_event(VK, MapVirtualKey(VK, 0), 0, 0); end;
  procedure Tf.UP  (VK: byte); begin keybd_event(VK, MapVirtualKey(VK, 0), KEYEVENTF_KEYUp, 0); end;

  procedure Tf.Key1(VK1: byte); begin
      Down(VK1);
      Up  (VK1);
  end;

  procedure Tf.Key2(VK1, VK2: byte); begin
      Down(VK1);
      Down(VK2);
      Up  (VK2);
      Up  (VK1);
  end;

  procedure Tf.Key3(VK1, VK2, VK3: byte); begin
      Down(VK1);
      Down(VK2);
      Down(VK3);
      Up  (VK3);
      Up  (VK2);
      Up  (VK1);
  end;

  end.
   
   
  //▓▓▓▓▓▓▓▓▓ DlgDebug_U.pas
  {*******************************************************************************
  程序中用來顯示調試信息的非模態對話框
  2005/02
  *******************************************************************************}
  unit DlgDebug_U; interface
  uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, ComCtrls;

  procedure deb(theMsg: string); overload;//Debug 信息
  procedure deb(theMsg: integer);overload;
  procedure deb(const theStr: string; const Args: array of const); overload;

  type
      TdlgDebug = class(TForm)
      re: TRichEdit;
      procedure mmKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
      procedure FormCreate(Sender: TObject);
      private
      { Private declarations }
      public
      { Public declarations }
      indent: byte;
      selColor: TColor;
      procedure TimeLine;
  end;

  var dlgDebug: TdlgDebug;
      dbg: Boolean;

  implementation
  {$R *.dfm}

  procedure TdlgDebug.mmKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
  begin
      if Key=VK_SPACE then begin
          re.Tag := integer( not boolean(re.Tag) );
          //mm.Tag := integer( not boolean(mm.Tag) );
          //if boolean(mm.Tag) then Red.Suspend
          //else Red.Resume;
      end;
  end;

  procedure deb(theMsg: string); begin
      if not dbg then exit;

      with dlgDebug do begin//Debug 信息
          TimeLine;
          re.SelAttributes.Color := selColor;
          re.paragraph.FirstIndent := indent;
          re.Lines.Add(theMsg);
          //mm.Lines.Add(theMsg);
      end;
  end;
  procedure deb(theMsg: integer);
  begin
      if not dbg then exit;

      with dlgDebug do begin//Debug 信息
          TimeLine;
          re.SelAttributes.Color := selColor;
          re.paragraph.FirstIndent := indent;
          re.Lines.Add(intToStr(theMsg));
          //mm.Lines.Add(intToStr(theMsg));
      end;
  end;
  procedure deb(const theStr: string; const Args: array of const); overload;
  begin
      if not dbg then exit;

      with dlgDebug do begin//Debug 信息
          TimeLine;
          re.SelAttributes.Color := selColor;
          re.paragraph.FirstIndent := indent;
          re.Lines.Add(format(theStr, Args));
          //mm.Lines.Add(format(theStr, Args));
      end;
  end;

  procedure TdlgDebug.TimeLine;
  begin with re do begin
      paragraph.FirstIndent := 0;
      SelAttributes.Color := clRed;
      lines.Add(formatDateTime(LongTimeFormat, now));
  end; end;

  procedure TdlgDebug.FormCreate(Sender: TObject);
  begin
      indent := 10;
      selColor := clYellow;
  end;

  end.
   
   
  //▓▓▓▓▓▓▓▓▓ HookPrj.dpr
  library HookPrj;

  uses
      SysUtils,
      Classes,
      Hook_U in 'Hook_U.pas';

  exports
      EnableWheelHook ,
      DisableWheelHook;

  begin
  end.
   
   
  //▓▓▓▓▓▓▓▓▓ Hook_U.pas
  unit Hook_U; interface

  uses Windows,Messages, SysUtils, dialogs;

  var HK: HHOOK;//鉤子的句柄值
      hFocus: HWnd;
      buf: array [0..1024] of char;
      sTitle: string;
      iC: byte;
      zDelta: short;

  
  function WheelHookProc(Code: Integer; WParam: Longint; Msg: Longint): LRESULT; stdcall;
  function EnableWheelHook : Boolean; stdcall; export;
  function DisableWheelHook: Boolean; stdcall; export;

  implementation

  //██████████████████████████████████▌處理鉤子
  function WheelHookProc(Code: Integer; WParam: Longint;Msg:Longint): LRESULT; stdcall;
  begin
      zDelta := short(HiWord(PMsg(Msg)^.wParam));

      if  (Code=HC_ACTION) and (PMsg(Msg)^.Message=WM_MOUSEWHEEL) and (abs(zDelta)>200) then begin
          hFocus := GetForegroundWindow;
          GetWindowText(hFocus, buf, 1024);
          sTitle := string(buf);

          if ( pos('mplayerc', sTitle)>0 )or( pos('Media Player Classic', sTitle)>0 ) then begin
              inc(iC);

              //按一次藍色側鍵產生兩條消息,二合一處理的話相當於快進1次,即5秒,
              //都處理的話相當於快進2次,即10秒
              //if (iC mod 2)=0 then begin
                  keybd_event(VK_Control, MapVirtualKey(VK_Control, 0), 0, 0);              //CTRL Down

                  if zDelta>200 then begin
                      keybd_event(VK_Right, MapVirtualKey(VK_Right, 0), 0, 0);              //RIGHT Down
                      keybd_event(VK_Right, MapVirtualKey(VK_Right, 0), KEYEVENTF_KEYUP, 0);//RIGHT Up
                  end else begin
                      keybd_event(VK_Left , MapVirtualKey(VK_Left , 0), 0, 0);              //LEFT  Down
                      keybd_event(VK_Left , MapVirtualKey(VK_Left , 0), KEYEVENTF_KEYUP, 0);//LEFT  Up
                  end;

                  keybd_event(VK_Control, MapVirtualKey(VK_Control, 0), KEYEVENTF_KEYUP, 0);//CTRL Up
              //end;

              PMsg(Msg)^.Message := 0;//因為側鍵消息已經本地處理過了,不必再交給其它線程處理
          end else Result := CallNextHookEx(HK, Code, WParam, Longint(@Msg));//如果不是MPC,則向下傳遞
      end else Result := CallNextHookEx(HK, Code, WParam, Longint(@Msg));//如果不是兩個藍色側鍵則向下傳遞
  end;

  function EnableWheelHook: Boolean; stdcall; export;//█████████ 加載鉤子
  begin
      if HK=0 then begin
          HK := SetWindowsHookEx(WH_GETMESSAGE, @WheelHookProc, Hinstance, 0);
          Result := True;
      end else Result := False;
  end;

  function DisableWheelHook: Boolean; stdcall; export;//████████▌卸載鉤子
  begin
      if HK<>0 then begin
          UnHookWindowsHookEx(HK);
          HK := 0;
          Result := True;
      end else Result := False;
  end;

  end.
  

  

  

  

  

  

  QQ:7995.7944(薪絲路)

  E-Mail:[email protected]


 
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved