beliebiger Rand
-
Hallo zusammen, ich arbeite mit VS 2008 Standard, C++ MFC. Wie kann man den Rand eines beliebigen CWnd-Fensters ( Steuerelemente, Views, Dialogfenster ) verändern bzw löschen, ohne Rand. Habe vielleicht nicht genügend lange gegoogelt. Weiss jemand Rat ?
-
Wenn ich dich richtig verstanden habe, willst du die Art des Randes ändern.
Also Größe ändern, 3D Stil,....Schau dir dazu im MSDN ModifyStyle und ModifyStyleEx an.
Das geht aber nur bei Standeardelementen.
Bei gerenderten Ansichten und ownerdrawn Elementen klappt das nur sehr selten.
-
Folgendes habe ich versucht, ohne Erfolg:
ModifyStyleEx(WS_EX_CLIENTEDGE, 0, SWP_DRAWFRAME); und:
ModifyStyleEx(WS_BORDER, 0, SWP_DRAWFRAME);Falsche Flags ?
-
Hast du dies in der OnCreate aufgerufen?
-
Für die CButton-Schaltfläche gibt es keine OnCreate-Funktion, die man editieren könnte. Bei dem Dialogfenster hat ModifyStyleEx(WS_BORDER, 0, 0); nicht funktioniert.
-
Es wird immer WM_CREATE aufgerufen. In einer MFC Anwendung und einem Diaog ist das Control allerdings schon da bis die MFC ins Spiel kommt. PreSubclassWnd wäre hier ein Ansatz.
Bestehende Controls kannst Du immer in OnInitDialag (OnInitialUpdate bei einem View) manipulieren. Ansonsten erzeugst Du die Controls ja sowieso selbst und kannst entsprechend handeln.
Nicht alle Controls erlauben solche Änderungen. Manche erlauben die Attribute Änderungen des Rahmens (WS_BORDER) nur in Erzeugungsphase und behandeln den Stil dot selbst.
Manche Controls zeichnen sich immer komplett selbst und haben auch keinen Rahmen in diesem Sinn...
-
Aber Martin, wieso geht folgendes nicht:
....OnInitDialog ...
CButton* bu = (CButton*)GetDlgItem(IDC_BUTTON1);
bu->ModifyStyleEx(WS_BORDER, 0, 0);Ich habe auch versucht, die CButton "von Hand" anzulegen, und bei Create, den
WS_BORDER Style nicht angegeben. Und der Rahmen ist noch da. An und für sich
bräuchte man das ja nicht, aber ich meine, was bei C# .NET geht, sollte auch bei
C++ MFC gehen. Zweigleisig ...
-
Weil .NET oft genug seinen eigenes Zeug intern macht und eben nicht die Standardklassen der API benutzt!
Ja! Insofern ist .NET zweigleisig... man kann viele Klassen nicht miteinander vergleichen.
-
Also nichts für ungut aber bei C# .NET heißt es nur:
button1.FlatStyle = FlatStyle.Flat;
button1.FlatAppearance.BorderSize = 0; // Kann überall stehen ...Irgendwie müsste es doch auch bei MFC möglich sein. Merkwürdig, dass es mit
ModifyStyleEx nicht geht. Auch wenn man die CButton selber anlegt, bekommt man
den Rahmen nicht weg. ja ich bin wirklich kein Spezialist für MFC. Da bewundere
ich Dich sehr. Also nichts für ungut ...
-
Du möchtest also einen „Button” ohne Rahmen, bei dem der Mauscursor eine andere Form annimmt...
Kann es sein, dass du zwar fragst, wie du etwas erreichen möchtest, aber nicht, was genau und warum?
Wenn es einfach ein Link sein soll, gibt es nämlich schon Standardcontrols (sowohl MFC als auch klassisch) dafür. Siehe z.B. How to Create SysLink Controls. Diese Links können sowohl eine url als auch eine ID sein und können auch in einem Text eingebettet sein.
-
Bau einen Ownerdraw Button.
Behandle WM_SETCURSOR.Siehe auch
https://www.codeproject.com/Articles/3430/A-Static-Hyperlink-control
https://www.codeguru.com/cpp/controls/staticctrl/article.php/c5801/Simple-Hyperlink-Static-Control.htm
-
WM_SETCURSOR verstehe ich, mit Ownerdraw habe ich mich noch nie beschäftigt. Man muss wohl eine Klasse von CButton ableiten, und DrawItem überschreiben. Anders als bei Subclassing, wird man eine CMyButton Schaltfläche per Code auf das Dialogfeld setzen müssen, nicht über die Toolbox. Könnte man da nicht auch OnPaint nehmen ? Ist es damit möglich, auf den Rahmen zu verzichten ? Ich bin nun mal kein Spezialist für MFC, ich kenne mich in anderen Gebieten aus, zB Compilerbau. ( Nur zur Entschuldigung ) ...
-
Ownerdraw ist zumindest die kürzere Variante, eigene Controls zu schreiben ist nicht sonderlich schwer, aber erfordert höheren Aufwand (auf wirklich alle erforderlichen Nachrichten reagieren, selber Nachrichten senden etc.).
Wenn du mit meinem Vorschlag, einfach einen Syslink zu nehmen, nicht einverstanden bist:
// Dialog-Klasse Dlg, auf WM_SETCURSOR und WM_DRAWITEM reagieren BEGIN_MESSAGE_MAP(Dlg, CDialog) ON_WM_SETCURSOR() ON_WM_DRAWITEM() END_MESSAGE_MAP() // OnDrawItem: void Dlg::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct) { if(nIDCtl == /*ID*/) { CWnd* b = GetDlgItem(/*ID*/); TCHAR wndText[64]; if(b->GetWindowTextLength()<_countof(wndText)) { b->GetWindowText(wndText, _countof(wndText)); ::DrawText(lpDrawItemStruct->hDC, wndText, _tcslen(wndText), &lpDrawItemStruct->rcItem, DT_CENTER | DT_VCENTER); } } else { CDialog::OnDrawItem(nIDCtl, lpDrawItemStruct); } }
Du kannst natürlich auch die CString-Funktionen nehmen, im Ressourceneditor muss für die entsprechenden Button(s) „Owner Draw” auf true gesetzt werden.
Für DrawText musst du dir noch die Doku anschauen, wenn der Text mehrere Linien einnehmen können oder anders ausgerichtet werden soll (es geht aber damit).Edit: Ob das Control den Fokus hat, ist nicht berücksichtigt, dies ist aber eigentlich noch zwingend erforderlich (siehe DrawFocusRect).
-
Das mit OwnerDraw verstehe ich nicht ganz. Aber so einen Aufwand nur um den Rahmen wegzukriegen. Warum ich das mache ? Ich will mich bilden, und das was bei C# geht, möchte ich auch bei MFC können, und umgekehrt. Zweigleisig !
Dann bedanke ich mich bei Euch ...
-
Es geht alles was auch in C# geht, aber eben anders. Oft auf einer niedrigeren Schiene.
Ich benutzte Bibliotheken wie die BCG-Control-Library da mache ich das und noch mehr Sachen mit einem Button. Aber intern basiert diese Klasse eben auch auf Ownerdraw...
Die C# Buttons basieren auch auf eher auf Ownerdraw Buttons... nur siehst Du das nicht. Die .NET Runtime verbirgt das vor Dir.
-
Ist die BCG-Control-Library kostenlos ?
-
Nein!
Auf dieser Bibliothek basieren alle CMfc... Klassen. Microsoft hat die Bibliothek von BCGSoft gekauft und selbst integriert.
Die BCG Bibliothek umfasst aber einiges mehr.
Aber solche "erweiterten Buttons" gibt es IMHO auch auf CodeProject.
-
Danke Martin !!!