天天看點

透視挂原理:透明視窗,畫框,畫線,繪制文字的實作(C++)

注意:需要開啟透明桌面效果

先上效果圖:

透視挂原理:透明視窗,畫框,畫線,繪制文字的實作(C++)

建立一個空項目,根據自己的D3D庫路徑導入D3D庫(這裡是用DrectX9,手賤畫了三根線,不用理):

透視挂原理:透明視窗,畫框,畫線,繪制文字的實作(C++)

建立一個預編譯.h頭檔案:

#pragma
 
#include <d3d9.h>
#include <d3dx9.h>
#pragma
#pragma
#include <dwmapi.h>
#pragma
 
#include <iostream>
#include<Windows.h>
 
using namespace std;      

D3D繪制.h:

#pragma
#include"預編譯.h"
 
/*
D3D相關的一些東西
如果不想用static變量用全局變量的話,千萬别再頭檔案聲明,在cpp檔案聲明後
再在頭檔案extern 類型名 變量名
*/
static MARGINS Margin;
static LPDIRECT3D9              g_pD3D = NULL;
static LPDIRECT3DDEVICE9        g_pd3dDevice = NULL;
static D3DPRESENT_PARAMETERS    g_d3dpp = {};
static ID3DXLine* pLine = 0;
static ID3DXFont* Font;
 
static HWND 輔助視窗句柄, GameHwnd;
static RECT 視窗矩形;
static int 視窗寬, 視窗高;
 
//注冊視窗需要用到的視窗類
static WNDCLASSEX wClass;
 
 
//畫矩形,文字之類的單獨放在這個函數裡
typedef void(*Draw)();
static Draw Render;
 
 
//視窗消息處理函數
LRESULT WinProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam);
 
bool 初始化D3D();
 
void 建立透明視窗(HWND 遊戲視窗句柄, Draw 繪制函數);
 
void 視窗消息循環();
 
void 畫線(D3DCOLOR Color, float X1, float Y1, float X2, float Y2, float Width);
 
void 繪制文字(float X, float Y, const char* Str, D3DCOLOR Color);
 
void 畫框(float X, float Y, float W, float H, float Width, D3DCOLOR Color);
 
void 繪制開始();
 
void 繪制結束();      

D3D繪制.cpp:

#include "D3D繪制.h"
 
bool 初始化D3D()
{
  /*
  D3D這玩意比較複雜,如果單純是想搞點輔助什麼的,複制粘貼我的足夠了,
  如果想深入學習,可能得另找資料了,下面的這些基本是固定的,想知道是用來幹啥的
  可以自行百度,我這個人比較懶。。。
  */
 
  if ((g_pD3D = Direct3DCreate9(D3D_SDK_VERSION)) == NULL)
    return false;
 
  // 建立D3D裝置
  ZeroMemory(&g_d3dpp, sizeof(g_d3dpp));
  g_d3dpp.Windowed = TRUE;
  g_d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
  g_d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
  g_d3dpp.EnableAutoDepthStencil = TRUE;
  g_d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
  g_d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
  if (g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, 輔助視窗句柄, D3DCREATE_HARDWARE_VERTEXPROCESSING, &g_d3dpp, &g_pd3dDevice) < 0)
    return false;
 
  if (pLine == NULL)
    D3DXCreateLine(g_pd3dDevice, &pLine);
 
  //建立D3D字型
  D3DXCreateFontW(g_pd3dDevice, 16, 0, FW_DONTCARE, D3DX_DEFAULT, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, FF_DONTCARE, L"Vernada", &Font);
 
  return true;
}
 
void 建立透明視窗(HWND 遊戲視窗句柄, Draw 繪制函數)
{
  if (繪制函數 == NULL || 遊戲視窗句柄 == 0) return;
 
  GameHwnd = 遊戲視窗句柄;
  Render = 繪制函數;
 
  //初始化視窗類
  wClass.cbClsExtra = NULL;
  wClass.cbSize = sizeof(WNDCLASSEX);
  wClass.cbWndExtra = NULL;
  wClass.hbrBackground = (HBRUSH)CreateSolidBrush(RGB(0, 0, 0));
  wClass.hCursor = LoadCursor(0, IDC_ARROW);
  wClass.hIcon = LoadIcon(0, IDI_APPLICATION);
  wClass.hIconSm = LoadIcon(0, IDI_APPLICATION);
  wClass.hInstance = GetModuleHandle(NULL);
  wClass.lpfnWndProc = (WNDPROC)WinProc;
  wClass.lpszClassName = L" ";
  wClass.lpszMenuName = L" ";
  wClass.style = CS_VREDRAW | CS_HREDRAW;
 
  //注冊視窗
  if (RegisterClassEx(&wClass) == 0)
  {
    MessageBox(NULL, L"建立視窗出錯!", L"提示!", 0);
    exit(1);
  }
 
  //建立視窗
  GetWindowRect(GameHwnd, &視窗矩形);
  視窗寬 = 視窗矩形.right - 視窗矩形.left;
  視窗高 = 視窗矩形.bottom - 視窗矩形.top;
  輔助視窗句柄 = CreateWindowEx(WS_EX_TOPMOST | WS_EX_TRANSPARENT | WS_EX_LAYERED, L" ", L" ", WS_POPUP, 1, 1, 視窗寬, 視窗高, 0, 0, 0, 0);
 
  //顯示視窗
  SetLayeredWindowAttributes(輔助視窗句柄, 0, RGB(0, 0, 0), LWA_COLORKEY);
  ShowWindow(輔助視窗句柄, SW_SHOW);
 
  初始化D3D();
}
 
void 視窗消息循環()
{
  while (1)
  {
    //使輔助視窗一直蓋在遊戲視窗上
    if (GameHwnd)
    {
      GetWindowRect(GameHwnd, &視窗矩形);
      視窗寬 = 視窗矩形.right - 視窗矩形.left;
      視窗高 = 視窗矩形.bottom - 視窗矩形.top;
      DWORD dwStyle = GetWindowLong(GameHwnd, GWL_STYLE);
      if (dwStyle & WS_BORDER)
      {
        視窗矩形.top += 23;
        視窗高 -= 23;
      }
      MoveWindow(輔助視窗句柄, 視窗矩形.left, 視窗矩形.top, 視窗寬, 視窗高, true);
    }
 
    //處理視窗消息
    MSG Message;
    ZeroMemory(&Message, sizeof(Message));
    if (PeekMessage(&Message, 0, 0, 0, PM_REMOVE))
    {
      DispatchMessage(&Message);
      TranslateMessage(&Message);
    }
 
    Sleep(1);
  }
 
 
  if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = NULL; }
  if (g_pD3D) { g_pD3D->Release(); g_pD3D = NULL; }
  CloseWindow(輔助視窗句柄);
 
  ::UnregisterClass(wClass.lpszClassName, wClass.hInstance);
}
 
LRESULT WinProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
  switch (Message)
  {
  case WM_PAINT:
    if(g_pd3dDevice)Render();//就是這裡調用了我們的畫框畫線之類的函數
    break;
 
  case WM_CREATE:
    DwmExtendFrameIntoClientArea(hWnd, &Margin);
    break;
 
  case WM_DESTROY:
  {
    g_pD3D->Release();
    g_pd3dDevice->Release();
    exit(1);
    return 0;
  }
  default:
    return DefWindowProc(hWnd, Message, wParam, lParam);
    break;
  }
  return 0;
}
 
void 畫線(D3DCOLOR Color, float X1, float Y1, float X2, float Y2, float Width)
{
  D3DXVECTOR2 Vertex[2] = { {X1,Y1},{X2,Y2} };
  pLine->SetWidth(Width);
  pLine->Draw(Vertex, 2, Color);
}
 
void 繪制文字(float X, float Y, const char* Str, D3DCOLOR Color)
{
  RECT Rect = { (LONG)X,(LONG)Y };
  Font->DrawTextA(NULL, Str, -1, &Rect, DT_CALCRECT, Color);
  Font->DrawTextA(NULL, Str, -1, &Rect, DT_LEFT, Color);
}
 
void 畫框(float X, float Y, float W, float H, float Width, D3DCOLOR Color)
{
  D3DXVECTOR2 Vertex[5] = { {X,Y},{X + W,Y},{X + W,Y + H},{X,Y + H},{X,Y} };
  pLine->SetWidth(Width);
  pLine->Draw(Vertex, 5, Color);
}
 
void 繪制開始()
{
  g_pd3dDevice->Clear(0, 0, D3DCLEAR_TARGET, 0, 1.0f, 0);
  g_pd3dDevice->BeginScene();
}
 
void 繪制結束()
{
  g_pd3dDevice->EndScene();
  g_pd3dDevice->Present(0, 0, 0, 0);
}      
#include"D3D繪制.h"
 
int 線粗 = 2;
D3DCOLOR 紅色 = D3DCOLOR_ARGB(255, 255, 255, 255);
 
void 繪制()
{
  繪制開始();
  畫線(D3DCOLOR_ARGB(255, 0, 0, 255), 20, 20, 66, 66,線粗);
  畫框(100, 100, 100, 100, 線粗, D3DCOLOR_ARGB(255, 255, 255, 0));
  繪制文字(200, 200, "吾無法無天", D3DCOLOR_ARGB(255, 255, 0, 255));
  繪制結束();
}
 
HWND 遊戲視窗 = (HWND)0x50A00;
void 開始()
{
  建立透明視窗(遊戲視窗, 繪制);
  視窗消息循環();
}
 
int main()
{
  CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)開始, NULL, 0, NULL);
 
  while (1)
  {
    cout << "輸入233關閉:" << endl;
    int a=0;
    cin >> a;
    if (a == 233)
    {
      return 0;
    }
  }
 
  return 0;
}