我的应用是DLL
,我正在将其注入(游戏)进程。
当我使用LoadBitmap()
并使用MAKEINTRESOURCE(IMAGE_RESOURCE_NAME)
喜欢这个:
MyImage = LoadBitmap(hInstance, MAKEINTRESOURCE(IMAGE_RESOURCE_NAME))
SendMessage(MyButton, BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)MyImage);
“创建按钮”代码:
MyButton = CreateWindow("BUTTON", "My Button", WS_VISIBLE | WS_CHILD | BS_BITMAP | BS_FLAT, 17, 18, 110, 30, hwnd, (HMENU)ButtonId, (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE), NULL);
LoadBitmap()
注入任何应用程序,但游戏时, DLL
起作用。
我认为是因为当我将DLL
注入游戏时,它不会从Resources
加载,并且图像也不会出现。因此我无法使用LoadBitmap
中的Resources
。 Resources
不会与DLL
数据一起进入Game
,并且游戏找不到资源,因此找不到图像。
因此,我还是尝试使用磁盘文件中的LoadImage()
。并以这种方式工作,并且图像出现在按钮上。
当我将其注入任何应用程序(如记事本)时,它会显示如下:
(这就是我想要的样子)
但是当我向游戏中注入DLL
时,该按钮会出现在边框和3D效果中:
经过大量搜索,我认为我要注入的游戏对我的DLL GUI Window
和不适用视觉样式按钮出现在Classy
外观中,边框和3D效果。甚至BS_FLAT
也不适用于该按钮。
这是我正在使用的完整代码:
#include "stdafx.h"
#include "Process.h"
#include <iostream>
#include <memory>
#include <string>
#include <vector>
#include <tchar.h>
#include "resource.h"
HINSTANCE hInstance;
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wc = { 0 };
HWND MainHwnd;
MSG Msg;
wc.cbSize = sizeof(wc);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.hbrBackground = (HBRUSH)(CreateSolidBrush(RGB(30, 30, 30)));
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.lpszMenuName = NULL;
wc.lpszClassName = "My Application";
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
if (!RegisterClassEx(&wc))
{
MessageBox(NULL, std::to_string(GetLastError()).c_str(), "RegisterClassEx!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
MainHwnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
"Application",
"My Application",
WS_SYSMENU | WS_OVERLAPPED | WS_CAPTION | WS_MINIMIZEBOX,
CW_USEDEFAULT, CW_USEDEFAULT, 400, 280,
NULL, NULL, hInstance, NULL);
if (MainHwnd == NULL)
{
MessageBox(NULL, std::to_string(GetLastError()).c_str(), "CreateWindow!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
ShowWindow(MainHwnd, nCmdShow);
UpdateWindow(MainHwnd);
while (GetMessage(&Msg, NULL, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return Msg.wParam;
}
int MyButtonId = 1000;
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_CREATE: {
HWND MyButton;
HBITMAP MyImage;
MyButton = CreateWindow("BUTTON", "A Button Text", WS_VISIBLE | WS_CHILD | BS_BITMAP | BS_FLAT, 17, 18, 110, 30, hwnd, (HMENU)MyButtonId, (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE), NULL);
///////// --->
// Here I'm using one of these :
// Using LoadImage()
MyImage = (HBITMAP)LoadImage(hInstance, "UI\\myimage.bmp", IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR | LR_DEFAULTSIZE | LR_LOADFROMFILE);
// Using LoadBitmap() | My_Bitmap is an image resource name
MyImage = LoadBitmap(hInstance, MAKEINTRESOURCE(My_Bitmap));
///////// <---
SendMessage(MyButton, BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)MyImage);
break;
}
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
}
unsigned long __stdcall Win_Thread(LPVOID Param)
{
WinMain(NULL, NULL, NULL, 1);
return 0;
}
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
// Set hInstance to hModule
hInstance = hModule;
CreateThread(0, 0, LPTHREAD_START_ROUTINE(Win_Thread), hModule, 0, 0);
}
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
我想我有两个选择。
1。。尝试使游戏从Resources
中找到我的图像,并使用LoadBitmap()
中的Resources
。因此该按钮将不会具有边框和3d效果。
2。。继续从磁盘文件中使用LoadImage()
,并尝试隐藏边框和3d效果,例如为我的DLL GUI启用视觉样式。 / p>
不幸的是,我什么也做不了,也不知道该怎么做,我正在整个互联网上搜索,却一无所获。
任何想法,我怎么能实现?
答案 0 :(得分:1)
不幸的是,您对LoadBitmap
的追求是一场狙击。视觉样式是导致外观不同的唯一原因。即使您获得了使用资源的代码,但除非启用视觉样式,否则外观还是错误的。
当主应用程序不使用Visual Styles时,MSDN专门针对在插件DLL中使用视觉样式提供了参考:
要点是,您需要使用ISOLATION_AWARE_ENABLED
宏并以动态样式显示DLL。
您还需要致电InitCommonControlsEx
。以上文档的其他几节中都提到了这一点。对于平面按钮,请传递ICC_STANDARD_CLASSES
标志(在结构内部)。
您的代码中确实有一些错误,即使您进行了表现和隔离,这些错误也可能阻止视觉样式正确激活。
您的DLL不应具有WinMain
函数。让一个函数执行从WinMain
和DLL线程调用的所有工作,而不是让DLL线程调用WinMain
。这本身并没有错,只是样式不好,但是它导致了下一个错误,这是一个更大的问题:
您的hInstance
参数隐藏了全局hInstance
变量,导致wc.hInstance
的值错误。如果WinMain
和DllMain
都设置了全局变量,然后所有其他代码都使用了全局变量,那么您就不会遇到这个问题。但是要修复此问题,需要在EXE而不是DLL中运行代码,这意味着从DLL线程中删除对WinMain
的调用。