- Katılım
- 10 Ocak 2009
- Konular
- 3,748
- Mesajlar
- 15,938
- Çözüm
- 334
- Online süresi
- 6mo 28d
- Reaksiyon Skoru
- 8,027
- Altın Konu
- 947
- Başarım Puanı
- 474
- Yaş
- 34
- MmoLira
- 86,651
- DevLira
- -12
ROHAN2 WORLD 1-120 TR TİPİ OFFICIAL YOHARA, BALATHOR VE AMON! 80. GÜNÜNDE! +10.000 ONLİNE! HİLE VE BOT %100 ENGELLİ HEMEN TIKLA!
[C++] Metin2 Client Window Centering Bug (Win10 / Win11)
Gerçek Sebep ve Kalıcı Çözüm
Gerçek Sebep ve Kalıcı Çözüm
Metin2 client’ında uzun zamandır var olan küçük ama fark edilen bir problem vardı.
Oyun penceresi açıldığında yatay eksende tam ortaya oturmuyordu.
Benim sistemimde bu fark yaklaşık 7 piksel civarındaydı.
Büyük bir şey değil ama “tam ortada değil” hissi net olarak vardı.
Before: pencere yatayda hafif sağa kayık
After: taskbar pozisyonu fark etmeksizin tam ortalanmış
Bu sorun basit bir matematik hatası değil.
Win10 / Win11 üzerinde:
- GetWindowRect() pencerenin gerçek görsel sınırlarını birebir yansıtmıyor
- DWM (Desktop Window Manager) nedeniyle pencerenin sol ve sağ çerçeveleri simetrik değil
Bu yüzden klasik olarak kullanılan:
Kod:
(screenWidth - windowWidth) / 2
Bu çalışmayla birlikte birkaç küçük ama önemli temizlik de yapıldı.
- Client penceresinin yatayda yaklaşık 7 piksel sağa kayık açılmasına sebep olan merkezleme mantığı düzeltildi
- Pencere artık kullanıcının gerçekten gördüğü frame’e göre ortalanıyor (Win10 / Win11 DWM uyumlu)
- GetWindowRect için yazılmış, WinAPI ismiyle çakışan gereksiz wrapper fonksiyon kaldırıldı
- FindWindow ile pencere başlığına bakarak yapılan “another window” reposition mantığı tamamen kaldırıldı
- Bu kod modern Windows sürümlerinde deterministik çalışmıyordu ve merkezlemeyi bozuyordu
- Sabit offset, magic number veya “biraz sola kaydır” tarzı hack’ler kullanılmadı
- Pencere artık her zaman work area içinde, taskbar’a taşmadan ve kayık olmadan açılıyor
Aşağıdaki video, yapılan değişiklikten sonraki sonucu gösteriyor:
Uygulama kısmı:
Client\\Source\\EterLib\\MSWindow.cpp dosyasında aşağıdaki wrapper fonksiyonu bulun ve silin:
Kod:
void CMSWindow::GetWindowRect(RECT* prc)
{
::GetWindowRect(m_hWnd, prc);
}
Ardından DWM uyumlu yeni yardımcı fonksiyonları ekleyin:
Kod:
static bool GetVisualWindowRect(HWND hwnd, RECT& outRect)
{
if (!::GetWindowRect(hwnd, &outRect))
return false;
using DwmGetWindowAttributeFn = HRESULT(WINAPI*)(HWND, DWORD, PVOID, DWORD);
constexpr DWORD ExtendedFrameBounds = 9;
static HMODULE s_dwm = ::LoadLibraryA("dwmapi.dll");
if (!s_dwm)
return true;
static auto s_getAttr =
reinterpret_cast<DwmGetWindowAttributeFn>(
::GetProcAddress(s_dwm, "DwmGetWindowAttribute"));
if (!s_getAttr)
return true;
RECT visual{};
if (SUCCEEDED(s_getAttr(hwnd, ExtendedFrameBounds, &visual, sizeof(visual))))
{
outRect = visual;
}
return true;
}
static POINT GetCenteredPosition(const RECT& visualRect, const RECT& workArea, const RECT& windowRect)
{
const int width = visualRect.right - visualRect.left;
const int height = visualRect.bottom - visualRect.top;
const int dx = visualRect.left - windowRect.left;
const int dy = visualRect.top - windowRect.top;
POINT pt{};
pt.x = workArea.left + ((workArea.right - workArea.left) - width) / 2 - dx;
pt.y = workArea.top + ((workArea.bottom - workArea.top) - height) / 2 - dy;
return pt;
}
CMSWindow::SetCenterPosition() fonksiyonunu aşağıdaki şekilde değiştirin:
Kod:
void CMSWindow::SetCenterPosition()
{
RECT window{};
RECT visual{};
RECT workArea{};
if (!::GetWindowRect(m_hWnd, &window))
return;
visual = window;
GetVisualWindowRect(m_hWnd, visual);
::SystemParametersInfo(SPI_GETWORKAREA, 0, &workArea, 0);
const POINT pos = GetCenteredPosition(visual, workArea, window);
SetPosition(pos.x, pos.y);
}
Client\\Source\\EterLib\\MSWindow.h dosyasında aşağıdaki tanımı silin:
Kod:
void GetWindowRect(RECT* prc);
Client\\Source\\UserInterface\\PythonApplication.cpp içinde aşağıdaki kodu bulun ve kaldırın:
Kod:
bool bAnotherWindow = false;
if (FindWindow(NULL, c_szName))
{
bAnotherWindow = true;
}
AdjustSize çağrısının hemen altına şunu ekleyin:
Kod:
CMSWindow::SetCenterPosition();
Ve aşağıdaki bloğu tamamen silin:
Kod:
if (bAnotherWindow)
{
RECT rc;
GetClientRect(&rc);
int windowWidth = rc.right - rc.left;
int windowHeight = rc.bottom - rc.top;
CMSApplication::SetPosition(
GetScreenWidth() - windowWidth,
GetScreenHeight() - 60 - windowHeight);
}
Bu değişiklikten sonra pencere artık piksel şaşması olmadan, taskbar konumundan bağımsız şekilde tam ortaya oturur.
Herhangi bir sabit offset veya geçici çözüm kullanılmaz, davranış tamamen deterministiktir.
Kaptan Yosun'dan alıntıdır. İyi kullanımlar dilerim.
- Katılım
- 1 Tem 2019
- Konular
- 1,893
- Mesajlar
- 5,201
- Çözüm
- 134
- Online süresi
- 1mo 8d
- Reaksiyon Skoru
- 4,001
- Altın Konu
- 140
- Başarım Puanı
- 339
- MmoLira
- 39,500
- DevLira
- 150
PAYLAŞIM İÇİN TEŞEKKÜRLER, ELİNİZE SAĞLIK ADMİNİM.
Şu an konuyu görüntüleyenler (Toplam : 0, Üye: 0, Misafir: 0)
Benzer konular
- Cevaplar
- 3
- Görüntüleme
- 379
- Kilitli
- Cevaplar
- 7
- Görüntüleme
- 1K
- Kilitli
- Cevaplar
- 1
- Görüntüleme
- 341














