Avatar billede martin181 Nybegynder
20. august 2003 - 15:08 Der er 16 kommentarer og
1 løsning

Task-skift i C++ program?

Hejsa!

Hvordan laver man et task skift i et C++ program?

Altså ligesom et skift med alt+tab fra eget program til andet?

Man skal kunne angive program/process...
Avatar billede segmose Nybegynder
20. august 2003 - 15:44 #1
Man kan frigive processoren fra et C++ ved et operativ system kald det er så ikke godt nok?
Avatar billede martin181 Nybegynder
20. august 2003 - 15:46 #2
Programmet skal stadigvæk leve - med snor i...

Frigiver man programmet kan man jo ikke det...
Avatar billede segmose Nybegynder
20. august 2003 - 16:11 #3
Det jeg mente var man kan frigave den nuværende time-slice til at de øvrige programmer kunne komme til.
Avatar billede bertelbrander Novice
20. august 2003 - 20:20 #4
Du burde kunne bruge følgende:
<code>
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>

int main(int argc, char *argv[])
{
  HWND handle;
  int i;

  if(argc != 2)
  {
    fprintf(stderr, "You must specify a window title (and nothing else)\n");
    return EXIT_FAILURE;
  }
  SetConsoleTitle(argv[0]); /* We don't want FindWindow to find us */

  if((handle = FindWindow(NULL, argv[1])) == 0)
  {
    fprintf(stderr, "Did not find your window\n");
    return EXIT_FAILURE;
  }
  SetForegroundWindow(handle);

  for(i = 0; i < 30; i++)
  {
    printf(".");
    fflush(stdout);
    Sleep(1000);
  }
  return EXIT_SUCCESS;
}
</code>
Du kalder programmet med titlen på det program du vil "task switch'e" til som parameter. Titlen er normalt det der står i det blå feldt øverst i vinduet.

Formålet med loopen med Sleep er udelukkende at vise at programmet fortsætter efter det har sat det andet program i forgrunden.
Avatar billede martin181 Nybegynder
21. august 2003 - 10:21 #5
Umiddelbart virker det godt nok - eneste lille minus er...

Hvis det vindue man vil vælge er minimeret - så forbliver det minimeret - men aktivt på proceslinien...

En anden lille ting: Kunne det ikke laves så det var procesnavnet - fra task mannager man kunne bruge? istedet for titlen på vinduet? Den bliver nem kringlet...
Avatar billede bertelbrander Novice
21. august 2003 - 17:48 #6
Den første del (hvis vinduet er minimeret) er ret let at løse, du indsætter disse to linier efter SetForegroundWindow(...):
if(IsIconic(handle))
  ShowWindow(handle, SW_RESTORE);

Den anden del er lidt mere besværligt, jeg vil se på det i aften.
Avatar billede martin181 Nybegynder
26. august 2003 - 08:56 #7
Hej Bertalbrander - det funger fint nok - din nye ide...

Men jeg er lidt spændt på at høre om du har fundet ud af noget mht. at kalde på procesnavnet...
Avatar billede bertelbrander Novice
26. august 2003 - 17:36 #8
Jeg har foreløbigt fundet ud af at det ikke er nemt at bruge process navnet, da der ikke er nogen let mapning mellem et process-navn og vindue. Jeg har dog ikke opgivet at finde en løsning.
Avatar billede bertelbrander Novice
27. august 2003 - 02:01 #9
Jeg har nu lavet en løsning hvor man angiver navnet på programmet (f.ex word.exe). Løsningen virker en anelse kringlet, og jeg er ikke sikker på at der ikke findes en enklere løsning, men det ser dog ud til at virke.
Når du bygger programmet skal du linke med Psapi.lib, kommandoen for BorlandC ser sådan ud:
bcc32 PSDK\Psapi.lib ps.c

<code>
#include <windows.h>
#include <psapi.h>
#include <stdlib.h>
#include <stdio.h>

void GetFileAndExt(const char *FullPath, char *Name)
{
  char Ext[MAX_PATH];
  _splitpath(FullPath, NULL, NULL, Name, Ext);
  strcat(Name, Ext);
}

HWND MatchingHWnd;

BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM Param)
{
  DWORD ProcessID = -1;

  GetWindowThreadProcessId(hwnd, &ProcessID);

  if(ProcessID == (DWORD )Param)
  {
    printf("Gotit %u\n", ProcessID);
    MatchingHWnd = hwnd;
    return FALSE;
  }
  return TRUE;
}

int main(int argc, char *argv[])
{
  DWORD Processes[1024], ProcessesNeeded;
  DWORD NumProcesses, i;
  int ProcessIndex;

  if(argc != 2)
  {
    printf("You have to specify which program you want to bring to front\n");
    return EXIT_FAILURE;
  }

  if(!EnumProcesses(Processes, sizeof(Processes), &ProcessesNeeded))
    return EXIT_FAILURE;

  NumProcesses = ProcessesNeeded/sizeof(DWORD);

  for(i = 0, ProcessIndex = -1; i < NumProcesses && ProcessIndex == -1; i++)
  {
    HMODULE ModHandle[1024];
    DWORD ModulesNeeded;
    HANDLE ProcessHandle;

    ProcessHandle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, Processes[i]);
    if(EnumProcessModules(ProcessHandle, ModHandle, sizeof(ModHandle), &ModulesNeeded))
    {
      char ModuleName[MAX_PATH], FileName[MAX_PATH];
      if(GetModuleFileNameEx(ProcessHandle, ModHandle[0], ModuleName, sizeof(ModuleName)))
      {
        GetFileAndExt(ModuleName, FileName);
        if(!stricmp(FileName, argv[1]))
        {
          printf("Found a match: %s\n", ModuleName);
          ProcessIndex = i;
        }
      }
    }
    CloseHandle(ProcessHandle);
  }
  if(ProcessIndex == -1)
  {
    printf("Did not find a match for %s\n", argv[1]);
    return EXIT_FAILURE;
  }
  EnumWindows(EnumWindowsProc, Processes[ProcessIndex]);
  if(!MatchingHWnd)
  {
    printf("Did not find the window\n");
    return EXIT_FAILURE;
  }
  SetForegroundWindow(MatchingHWnd);
  if(IsIconic(MatchingHWnd))
    ShowWindow(MatchingHWnd, SW_RESTORE);

  return EXIT_SUCCESS;
}
</code>
Avatar billede martin181 Nybegynder
28. august 2003 - 09:07 #10
Jeg prøver at se om det kan komme til at virke her - melder tilbage senere...
Avatar billede bertelbrander Novice
06. september 2003 - 02:17 #11
Jeg har lavet en lidt enklere løsning:

#include <windows.h>
#include <psapi.h>
#include <stdlib.h>
#include <stdio.h>

void GetFileAndExt(const char *FullPath, char *Name)
{
  char Ext[MAX_PATH];
  _splitpath(FullPath, NULL, NULL, Name, Ext);
  strcat(Name, Ext);
}

HWND MatchingHWnd;

BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM Param)
{
  DWORD ProcessID = -1;
  HANDLE ProcessHandle;
  HMODULE ModHandle[1024];
  DWORD ModulesNeeded;
  BOOL Proceed = TRUE;

  GetWindowThreadProcessId(hwnd, &ProcessID);

  ProcessHandle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, ProcessID);
  if(EnumProcessModules(ProcessHandle, ModHandle, sizeof(ModHandle), &ModulesNeeded))
  {
    char ModuleName[MAX_PATH], FileName[MAX_PATH];
    if(GetModuleFileNameEx(ProcessHandle, ModHandle[0], ModuleName, sizeof(ModuleName)))
    {
      GetFileAndExt(ModuleName, FileName);
      if(!stricmp(FileName, (char *)Param))
      {
        printf("Found a match: %s\n", ModuleName);
        MatchingHWnd = hwnd;
        Proceed = FALSE;
      }
    }
  }
  CloseHandle(ProcessHandle);

  return Proceed;
}

int main(int argc, char *argv[])
{
  if(argc != 2)
  {
    printf("You have to specify which program you want to bring to front\n");
    return EXIT_FAILURE;
  }
  EnumWindows(EnumWindowsProc, (LPARAM )argv[1]);
  if(!MatchingHWnd)
  {
    printf("Did not find the window\n");
    return EXIT_FAILURE;
  }
  SetForegroundWindow(MatchingHWnd);
  if(IsIconic(MatchingHWnd))
    ShowWindow(MatchingHWnd, SW_RESTORE);

  return EXIT_SUCCESS;
}
Avatar billede martin181 Nybegynder
08. september 2003 - 09:20 #12
prøver med det nye forslag...
Avatar billede bertelbrander Novice
18. september 2003 - 00:00 #13
Jeg har rodet lidt mere med projectet og fundet ud af den metode der er brugt i de to sidste kode eksempler ikke er sikker.
Problemet er at en process godt kan have mere end et top level vindue, selv om der kun kører en instans af programmet.
Det gør det lidt svært at finde ud af hvilket vindue der skal skiftes til.
Den første metode (hvor man finder vinduet vha vindues titlen) er sikker, men gør at man skal kende titlen på vinduet. Man kan evt indsætte følgende efter  SetForegroundWindow(handle), hvis man vil håndtere minimerede vinduer:

if(IsIconic(handle))
  ShowWindow(handle, SW_RESTORE);

Hvis man vil finde vinduet der skal skiftes til, ud fra program navnet (som i de to seneste eksempler), kan man bruge følgede forbedrede version:

#include <windows.h>
#include <psapi.h>
#include <stdlib.h>
#include <stdio.h>

void GetFileAndExt(const char *FullPath, char *Name)
{
  char Ext[MAX_PATH];
  _splitpath(FullPath, NULL, NULL, Name, Ext);
  strcat(Name, Ext);
}

BOOL MatchFound;

BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM Param)
{
  DWORD ProcessID = -1;
  HANDLE ProcessHandle;
  HMODULE ModHandle[1024];
  DWORD ModulesNeeded;
  char text[1024] = "";

  GetWindowThreadProcessId(hwnd, &ProcessID);

  ProcessHandle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, ProcessID);
  if(EnumProcessModules(ProcessHandle, ModHandle, sizeof(ModHandle), &ModulesNeeded))
  {
    char ModuleName[MAX_PATH], FileName[MAX_PATH];
    if(GetModuleFileNameEx(ProcessHandle, ModHandle[0], ModuleName, sizeof(ModuleName)))
    {
      GetFileAndExt(ModuleName, FileName);
      if(!stricmp(FileName, (char *)Param))
      {
        GetWindowText(hwnd, text, 1024);
        printf("Found a match: %s\nTitle: %s\n", ModuleName, text);
        if(text[0])
        {
          SetForegroundWindow(hwnd);
          if(IsIconic(hwnd))
            ShowWindow(hwnd, SW_RESTORE);
          MatchFound = TRUE;
        }
      }
    }
  }
  CloseHandle(ProcessHandle);

  return TRUE;
}

int main(int argc, char *argv[])
{
  int i;

  if(argc != 2)
  {
    printf("You have to specify which program you want to bring to front\n");
    return EXIT_FAILURE;
  }
  EnumWindows(EnumWindowsProc, (LPARAM )argv[1]);
  if(!MatchFound)
  {
    printf("Did not find the window\n");
    return EXIT_FAILURE;
  }

  for(i = 0; i < 30; i++)
  {
    printf(".");
    fflush(stdout);
    Sleep(1000);
  }

  return EXIT_SUCCESS;
}

Forskellen fra de tidligere versioner er at man restorer alle vinduer der stammer fra program navnet, hvis de har en titel. Metoden er statig ikke helt sikker, men dog bedre end de tidligere.
Avatar billede martin181 Nybegynder
22. september 2003 - 13:33 #14
Hejsa!

Det hjalp på vores problem.... tak for hjælpen... smider du et svar? så du kan få dine fortjente point?
Avatar billede martin181 Nybegynder
04. november 2003 - 10:16 #15
Svar udbedes :-)
Avatar billede bertelbrander Novice
04. november 2003 - 20:13 #16
Jeg forsøger at undgå point.
Avatar billede martin181 Nybegynder
05. november 2003 - 09:12 #17
Okay - så skal du nok blive fri :-)

Rart at der er nogen der vil hjælpe uden belønning :-)

Igen - mange tak for hjælpen :-)
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