Avatar billede martinr Nybegynder
21. februar 2004 - 20:16 Der er 6 kommentarer og
1 løsning

Ændre rækkefølgen af åbne vinduer

Er det muligt via kode at ændre rækkefølgen af de åbne vinduer (dem man ser nederst i proceslinien)?

Jeg ved, det er muligt at hente en liste over de åbne vinduer, men jeg kunne godt tænke mig at ændre i rækkefølgen således, at jeg kan flytte et åbent vindue frem og tilbage på proceslinien.

Hvis det overhovedet er muligt, ville det også være rart med noget kode.

På forhånd mange tak.
Avatar billede hrc Mester
29. februar 2004 - 23:09 #1
Jeg fandt dette link hvor der også er source. Prøver at konvertere det til noget Delphisk, men antager at du gerne selv vil kigge lidt på koden også.

http://www.codeproject.com/tools/tbarsort.asp
Avatar billede hrc Mester
01. marts 2004 - 13:41 #2
Som programmøren selv skriver, så er der tilsyneladende ingen måde at lege direkte med processlinien. Det løses ved at lukke og åbne de fundne vinduer i den rækkefølge som de skal vises i listen. Det flimrer lidt, men det virker.

Har lige kopieret koden ud (det er ulæseligt men det er fordi det er C++ syntaks ;-))

  int nNumItems = m_listWindows.GetCount();
  for (int n = 0; n < nNumItems; n++)
  {
    HWND hwnd = (HWND)m_listWindows.GetItemData(n);
    ::ShowWindow(hwnd, SW_HIDE);
    ::ShowWindow(hwnd, SW_SHOW);
  }
  // now hide and show self
  ShowWindow(SW_HIDE);
  ShowWindow(SW_SHOW);
  SetForegroundWindow();

Spøg til side (men C++ syntaksen er altså slem), så findes ShowWindow i Dwlphi, så det sværeste er at skaffe en liste af vinduer. Her gennemsøger han alle og tager de der ikke har en owner => de er main-applikationen. Funktioenen er vist nedenfor:

/*static */BOOL CALLBACK CTaskbarSortDlg::ListWindows(HWND hwnd, LPARAM lparam)
{
  // lParam is the dialog
  BOOL bRetVal = TRUE;
  CTaskbarSortDlg* pDlg = (CTaskbarSortDlg*)lparam;
  char *lpsz;
  int nTitleLength;
  int nIndex;
 
  // tried: IsWindow(hwnd) - didn't filter out any
  // tried: IsWindowEnabled(hwnd) - filtered out threads (OLE etc)
  if (hwnd == pDlg->GetSafeHwnd())
  {
    // don't process this window
    TRACE0("This window!\n");
  }
  else if (::GetParent(hwnd) != NULL)  // owned - won't be in taskbar
  {
    //TRACE0("Owned window\n");
  }
  else if (::GetWindowLong(hwnd, GWL_EXSTYLE) & WS_EX_TOOLWINDOW)
  {
    //TRACE0("Window is a tool window\n");
  }
  else if (!::IsWindowVisible(hwnd))
  {
    //TRACE0("Window not visible\n");
  }
  else if ((nTitleLength = ::GetWindowTextLength(hwnd)) == 0)
  {
    // no title!
    //TRACE0("Window has no title\n");
  }
  else
  {
    nTitleLength++;
    lpsz = new char[nTitleLength];
    if (::GetWindowText(hwnd, lpsz, nTitleLength) == 0)
    {
      // must be an error!
      TRACE0("Error getting window text\n");
      bRetVal = FALSE;
    }
    else if (stricmp(lpsz, "Program Manager") != 0)
    {
      if ((nIndex = pDlg->m_listWindows.AddString(lpsz)) == LB_ERR)
      {
    TRACE0("Error adding string\n");
      }
      else if (nIndex == LB_ERRSPACE)
      {
    // out of room - fatal error
    TRACE0("Error adding string: no room\n");
    bRetVal = FALSE;
      }
      else if (pDlg->m_listWindows.SetItemData(nIndex,(DWORD)hwnd) == LB_ERR)
      {
    TRACE0("Error setting item data\n");
      }
    }
    delete lpsz;
  }
  return bRetVal;
}

Jeg søgte lidt videre på nettet og fandt et eksempel som jeg tilrettede til følgende:

function FindWindows(aWindows: TStrings): longint;
const
  StLgd = 255;
var
  hWndCurWin, hWndDesk: HWnd;
  szWinText: pChar;
  WinText: string;
  foundAt: byte;
  bNoGo : boolean;
begin
  result := -1;
  hWndDesk:= GetDesktopWindow;

  aWindows.Clear;

  {This ist the parent of alle top-level windows}
  if hWndDesk <> 0 then
    hWndCurWin := GetWindow(hWndDesk,GW_CHILD)
  else {place error handling here}
    exit;

  if not assigned(aWindows) then
    exit; {you have to create Stringlist before passing the variable to this function}

  getMem(szWinText,StLgd+1);
  try
    while (hWndCurWin <> 0) do begin
      GetWindowText(hWndCurWin, szWinText,StLgd);

      bNoGo := false;
      WinText:= strpas(szWinText);
      if GetParent(hWndCurWin) <> 0 then // Parents
        bNoGo := true;

      if ((GetWindowLong(hWndCurWin, GWL_EXSTYLE) and WS_EX_TOOLWINDOW) <> 0) then // Tool window
        bNoGo := true;

      if IsWindowVisible(hWndCurWin) then // Visible
        bNoGo := true;

      if WinText = '' then // No title
        bNoGo := true;

      if not bNoGo then
        aWindows.AddObject(WinText,TObject(hWndCurWin));

      hWndCurWin := GetWindow(hWndCurWin,GW_HWNDNEXT);
    end;
    result := aWindows.Count;
  finally
    freeMem(szWinText,StLgd+1);
  end; // try
end;

Der kommer lidt for mange vinduer til, men det er fremskridt. Bemærk, i øvrigt at hver linie i TStrings (eller en nedarving af) indeholder handle til vindue i aWindows.Lines.Objects[index] - den er altså let at få fat på når du skal fjerne og sætte den igen.
Avatar billede martinr Nybegynder
01. marts 2004 - 17:13 #3
Ok, tak, har prøvet programmet og det virker sådan som jeg ønsker det.

Nu er det bare sådan, at jeg gerne vil have sourcekoden konverteret til Delphi, så jeg kan lave min egen version af programmet, og jeg kender næsten intet til C++ (jeg forstår næsten ingenting af koden foroven).

Jeg vil høre, om det på en eller anden måde er muligt på en (forholdsvis) nem måde at få koden lavet om til brugbar Delphi kode, eller om nogle af jer super programmøre derude evt. gider at skrive Delphi koden.

Jeg vil gerne smide nogle flere point i, hvis det er.

Jeg takker for jeres hjælp.
Avatar billede hrc Mester
02. marts 2004 - 17:21 #4
Er det bare kernen i programmet eller skal det ligne det? For kernen er mere eller mindre ovenfor. Jeg skal gerne prøve at strikke noget sammen til dig - gi' mig lige en dags tid.
Avatar billede hrc Mester
03. marts 2004 - 00:13 #5
Nu har jeg lidt du kan lege med. Send en mail til "hrc_public snabela hotmail dot com" og jeg vil sende det til dig ASAP.
Avatar billede martinr Nybegynder
03. juni 2004 - 04:40 #6
Undskyld jeg ikke har svaret så længe.

Jeg takker mange gange for din hjælp, har leget lidt med det og fået det til at virke. Jeg håber bare en dag, at jeg også kan få ikonerne med for hvert vindue i listen.
Avatar billede hrc Mester
03. juni 2004 - 09:59 #7
Jeg er desværre ikke kommet direkte videre, men har rodet en del med andre ting der måske kan bruges - vender nok tilbage snart. Problemet med det eksempel jeg konverterede til Delphi er, at det var baseret på MFC-klasserne (klasser, ha! Sgu ikke objektklasser ;-)) og det lykkes mig ikke at gøre noget tilsvarende i Delphi.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester