2016-10-19 5 views
0

Je travaille sur une base de code héritée (1999), qui présente un bug ennuyeux lorsque le défilement de certains éléments de l'interface graphique ne s'affiche pas correctement lorsque la fenêtre est placée sur un non-primaire. moniteur. Dans la mesure où je peux comprendre (n'étant pas très familier avec les API de Windows) le problème est que le code récupère le DeviceContext pour dessiner à l'aide GetDC(hwnd), qui de ce que je peux faire sur les docs obtient un DC pour le moniteur primaire seulement (mais les docs ne sont pas très clairs, TBH).Création d'un DeviceContext relatif à plusieurs fenêtres sur plusieurs moniteurs

J'ai réussi à dessiner des choses sur l'écran, en utilisant essentiellement:

RECT rect; 
GetWindowRect(hwnd, &rect); 
HMONITOR monitor = MonitorFromRect(&rect, MONITOR_DEFAULTTOPRIMARY); 
MONITORINFOEX minfo; 
minfo.cbSize = sizeof(MONITORINFOEX); 
GetMonitorInfo(monitor, &minfo); 
HDC = CreateDC(NULL, minfo.szDevice, NULL, NULL); 

Cela fait bouger les choses tirées sur le moniteur correct, mais l'application s'attend clairement quelque chose qui fenêtre relative, parce que tout se retrouve dans le coin supérieur gauche du bureau et non dans la fenêtre.

Maintenant, mon googling semble indiquer que l'exécution du code de peinture deux fois en utilisant EnumDisplayMonitors(GetDC(), &rect, PaintCallback, NULL) devrait faire le bon choix. Malheureusement, mon code n'est pas C ou C++. C'est une image SmallTalk (et la prise en charge a pris fin il y a 15 ans environ), et je ne suis tout simplement pas sûr que le traitement de la couleur se fasse dans le code auquel j'ai accès, ou s'il est suffisamment profond tripes du SmallTalk que je ne peux pas y arriver.

Donc ma question: est-il possible de créer un DC qui est relatif à la zone client de ma fenêtre (en ajustant le DC de CreateDC peut-être)? Je me rends compte que cela va probablement casser si la fenêtre chevauche deux moniteurs, mais c'est au moins moins cassé que l'état actuel des choses.

MISE À JOUR:

J'ai réussi à exécuter le code de rendu deux fois, en utilisant EnumDisplayMonitors, mais que les accidents de manière étrange (ce qui est très probablement un problème de Smalltalk, le compilateur est vieux et idiosyncrasique, mais le code de débogage cette profondément dans la pile est problématique).

Pour répondre aux commentaires: Je pense que le code veut essentiellement dessiner sur les fenêtres, oui. Les objets SmallTalk représentant les différents éléments de l'interface graphique portent des poignées de fenêtre qui sont utilisées pour créer des contrôleurs de domaine avec GetDC(hwnd), ce qui est assez facile. Donc, il semble GetDC(hwnd)devrait obtenir un DC qui fait la bonne chose, dans ce cas; il se peut que le code ST cache les contrôleurs de domaine quelque part et que GetDC renvoie un contrôleur de domaine différent lorsque la fenêtre est déplacée vers un autre écran (ce qui semble plausible d'après ma connaissance superficielle).

+0

On dirait que vous voulez dessiner sur une fenêtre. Utilisez 'FindWindow' pour obtenir un handle de fenêtre ou utilisez l'utilitaire Spy ++ dans Visual Studio pour trouver le handle de fenêtre. Créez le DC: 'HDC hdc = GetDC (hwnd)', et appelez 'ReleaseDC (hwnd, hdc)' lorsque vous avez terminé. Mais c'est un bidouillage bon marché bien sûr, vos dessins seront effacés très rapidement. Pourquoi ne le faites-vous pas correctement en créant votre propre fenêtre? –

+0

Je ne pense pas que le problème est lié à GetDC lui-même. Peut-être qu'il y a aussi du code qui utilise GetClientRect/GetWindowRect et les coordonnées sont prises par rapport à l'écran principal en quelque sorte. – VuVirt

Répondre

0

Il semble que le problème était en fait la mise en cache des contrôleurs de domaine créés par GetDC. J'ai piraté le code de rendu pour ne pas utiliser les caches (plus ou moins, le code est un peu emmêlé), et d'un premier coup d'oeil, il semble que cela a fait l'affaire. Pour la postérité, au cas où quelqu'un google pour Visual Smalltalk Enterprise et trouve cette réponse, ce que j'ai fait était d'éditer GraphicsTool>>ifNilHandle: pour ne pas réellement vérifier si le handle est nul, mais toujours exécuter le bloc pour obtenir un nouveau handle et retourner vrai à la fin. De cette façon, les nouveaux DC sont récupérés à chaque fois.

MISE À JOUR:

Cela corrige le problème immédiat que je tentais de corriger, mais malheureusement casse deux autres (notamment WindowBuilder Pro, l'outil kit de construction GUI). Le problème est clairement la mise en antémémoire des contrôleurs de domaine quelque part dans le code, mais elle doit être résolue d'une manière beaucoup plus ciblée que l'approche de masse ci-dessus.