1 Востаннє редагувалося alona.riaba (12.05.2017 19:21:11)

Тема: Можливість вибору програми, що запускається, з декількох варіантів

Допоможіть будь ласка, новачок в цьому, але треба терміново.
Є програма(проект win32) на С++ її треба змінити щоб виконувалось наступне, в мене не виходить зробити завдання, не можу зрозуміти про що йде мова:

Завдання:  Додати в програму можливість вибору програми, що запускається, з декількох варіантів
(наприклад, зі списку), передбачити можливість вибіркового завершення
процесів.

Код програми:

#include <windows.h>
#include <stdio.h>
#include "proc.h"
LRESULT CALLBACK ProcessesWndProc(HWND, UINT, UINT, LONG);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    LPSTR lpszCmdParam, int nCmdShow)
{
    HWND hWnd;
    WNDCLASS WndClass;
    MSG Msg;
    char szClassName[] = "Processes";
    WndClass.style = CS_HREDRAW | CS_VREDRAW;
    WndClass.lpfnWndProc = ProcessesWndProc;
    WndClass.cbClsExtra = 0;
    WndClass.cbWndExtra = 0;
    WndClass.hInstance = hInstance;
    WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
    WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    WndClass.lpszMenuName = "ProcessesMenu";
    WndClass.lpszClassName = szClassName;
    if (!RegisterClass(&WndClass))
    {
        MessageBox(NULL, "Cannot register class", "Error", MB_OK);
        return 0;
    }
    hWnd = CreateWindow(szClassName, "Processes Demo",
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT,
        CW_USEDEFAULT, CW_USEDEFAULT,
        NULL, NULL, hInstance, NULL);
    if (!hWnd)
    {
        MessageBox(NULL, "Cannot create window", "Error", MB_OK);
        return 0;
    }
    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);
    while (GetMessage(&Msg, NULL, 0, 0))
    {
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
    }
    return Msg.wParam;
}
LRESULT CALLBACK ProcessesWndProc(HWND hWnd, UINT Message,
    UINT wParam, LONG lParam)
{
    const int Max = 10;
    STARTUPINFO StartupInfo;
    static int ProcessNumber = 2;
    static PROCESS_INFORMATION ProcessInformation[Max];
    static char cMyMessage[80];
    static HMENU hSubMenu;
    switch (Message)
    {
    case WM_CREATE:
        hSubMenu = GetSubMenu(GetMenu(hWnd), 0);
        return 0;
    case WM_COMMAND:
        switch (LOWORD(wParam))
        {
        case IDM_New_Process:
            if (ProcessNumber < Max)
            {
                StartupInfo.cb = sizeof(STARTUPINFO);
                StartupInfo.lpReserved = NULL;
                StartupInfo.lpDesktop = NULL;
                StartupInfo.lpTitle = NULL;
                StartupInfo.dwFlags = STARTF_USESHOWWINDOW;
                StartupInfo.wShowWindow = SW_SHOWNORMAL;
                StartupInfo.cbReserved2 = 0;
                StartupInfo.lpReserved2 = NULL;
                if (CreateProcess(NULL, "Notepad.exe",
                    NULL, NULL, FALSE, 0,
                    NULL, NULL, &StartupInfo,
                    &(ProcessInformation[ProcessNumber])))
                {
                    ProcessNumber++;
                    wsprintf(cMyMessage, "hProcess is %x.\nThread is %x.\ndwProcessId is %x.\ndwThreadId is %x.", 
                        ProcessInformation[ProcessNumber -
                        1].hProcess,
                        ProcessInformation[ProcessNumber -
                        1].hThread,
                        ProcessInformation[ProcessNumber -
                        1].dwProcessId,
                        ProcessInformation[ProcessNumber -
                        1].dwThreadId);
                    MessageBox(hWnd, cMyMessage, "Process is created", MB_OK);
                 EnableMenuItem(hSubMenu, IDM_Kill_Process,
                            MF_BYCOMMAND | MF_ENABLED);
                }
                else
                    MessageBox(hWnd, "Cannot create process",
                        "Process creation", MB_OK);
            }
            else
            {
                MessageBox(hWnd, "Too many created processes...",
                    "Process creation", MB_OK);
            }
            break;
        case IDM_Kill_Process:
            if (ProcessNumber > 0)
            {
                if (TerminateProcess(ProcessInformation[ProcessNumber - 1].hProcess,
                    0))
                {
                    ProcessNumber - 0;
                    if (!ProcessNumber)
                        EnableMenuItem(hSubMenu, IDM_Kill_Process,
                            MF_BYCOMMAND |
                            MF_GRAYED);
                }
                else
                    MessageBox(hWnd, "Cannot terminate process",
                        "Process termination", MB_OK);
            }
            else MessageBox(hWnd, "No more processes", "Process termination", MB_OK);
                break;
        case IDM_Exit:
            SendMessage(hWnd, WM_CLOSE, 0, 0);
            break;
        }
        return 0;
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hWnd, Message, wParam, lParam);
}

2

Re: Можливість вибору програми, що запускається, з декількох варіантів

Щодо запуску зі списку можна спробувати так:

// Win32Project1.cpp: определяет точку входа для приложения.
//

#include "stdafx.h"
#include "Win32Project1.h"
#include <Windows.h>

#define MAX_LOADSTRING 100

// Глобальные переменные:
HINSTANCE hInst;                                // текущий экземпляр
WCHAR szTitle[MAX_LOADSTRING];                  // Текст строки заголовка
WCHAR szWindowClass[MAX_LOADSTRING];            // имя класса главного окна

// Отправить объявления функций, включенных в этот модуль кода:
ATOM                MyRegisterClass(HINSTANCE hInstance);
BOOL                InitInstance(HINSTANCE, int);
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);

int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPWSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

    // TODO: разместите код здесь.

    // Инициализация глобальных строк
    LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    LoadStringW(hInstance, IDC_WIN32PROJECT1, szWindowClass, MAX_LOADSTRING);
    MyRegisterClass(hInstance);

    // Выполнить инициализацию приложения:
    if (!InitInstance (hInstance, nCmdShow))
    {
        return FALSE;
    }

    HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WIN32PROJECT1));

    MSG msg;

    // Цикл основного сообщения:
    while (GetMessage(&msg, nullptr, 0, 0))
    {
        if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    return (int) msg.wParam;
}



//
//  ФУНКЦИЯ: MyRegisterClass()
//
//  НАЗНАЧЕНИЕ: регистрирует класс окна.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEXW wcex;

    wcex.cbSize = sizeof(WNDCLASSEX);

    wcex.style          = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = WndProc;
    wcex.cbClsExtra     = 0;
    wcex.cbWndExtra     = 0;
    wcex.hInstance      = hInstance;
    wcex.hIcon          = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WIN32PROJECT1));
    wcex.hCursor        = LoadCursor(nullptr, IDC_ARROW);
    wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName   = MAKEINTRESOURCEW(IDC_WIN32PROJECT1);
    wcex.lpszClassName  = szWindowClass;
    wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

    return RegisterClassExW(&wcex);
}

//
//   ФУНКЦИЯ: InitInstance(HINSTANCE, int)
//
//   НАЗНАЧЕНИЕ: сохраняет обработку экземпляра и создает главное окно.
//
//   КОММЕНТАРИИ:
//
//        В данной функции дескриптор экземпляра сохраняется в глобальной переменной, а также
//        создается и выводится на экран главное окно программы.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   hInst = hInstance; // Сохранить дескриптор экземпляра в глобальной переменной

   HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);

   if (!hWnd)
   {
      return FALSE;
   }
   int xpos = 10;            // Horizontal position of the window.
   int ypos = 10;            // Vertical position of the window.
   int nwidth = 200;          // Width of the window
   int nheight = 200;         // Height of the window
   HWND hwndParent = hWnd; // Handle to the parent window

   HWND hWndComboBox = CreateWindow(L"COMBOBOX", TEXT(""),
       CBS_DROPDOWN | CBS_HASSTRINGS | WS_CHILD | WS_OVERLAPPED | WS_VISIBLE,
       xpos, ypos, nwidth, nheight, hwndParent, NULL, hInstance,
       NULL);
   SendMessage(hWndComboBox, (UINT)CB_ADDSTRING, (WPARAM)0, (LPARAM)TEXT("Notepad.exe"));
   SendMessage(hWndComboBox, (UINT)CB_ADDSTRING, (WPARAM)0, (LPARAM)TEXT("calc.exe"));

   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);

   return TRUE;
}

//
//  ФУНКЦИЯ: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  НАЗНАЧЕНИЕ:  обрабатывает сообщения в главном окне.
//
//  WM_COMMAND — обработать меню приложения
//  WM_PAINT — отрисовать главное окно
//  WM_DESTROY — отправить сообщение о выходе и вернуться
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_COMMAND:
        {
        if (HIWORD(wParam) == CBN_SELCHANGE) {
            int ItemIndex = SendMessage((HWND)lParam, (UINT)CB_GETCURSEL,(WPARAM)0, (LPARAM)0);
            TCHAR  ListItem[256];
            (TCHAR)SendMessage((HWND)lParam, (UINT)CB_GETLBTEXT,(WPARAM)ItemIndex, (LPARAM)ListItem);
            STARTUPINFO StartupInfo;
            StartupInfo.cb = sizeof(STARTUPINFO);
            StartupInfo.lpReserved = NULL;
            StartupInfo.lpDesktop = NULL;
            StartupInfo.lpTitle = NULL;
            StartupInfo.dwFlags = STARTF_USESHOWWINDOW;
            StartupInfo.wShowWindow = SW_SHOWNORMAL;
            StartupInfo.cbReserved2 = 0;
            StartupInfo.lpReserved2 = NULL;
            PROCESS_INFORMATION ProcessInformation;
            CreateProcess(NULL, (LPWSTR)ListItem,
                NULL, NULL, FALSE, 0,
                NULL, NULL, &StartupInfo,
                &(ProcessInformation));
        };
            int wmId = LOWORD(wParam);
            // Разобрать выбор в меню:
            switch (wmId)
            {
            case IDM_ABOUT:
                DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
                break;
            case IDM_EXIT:
                DestroyWindow(hWnd);
                break;
            default:
                return DefWindowProc(hWnd, message, wParam, lParam);
            }
        }
        break;
    case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hWnd, &ps);
            // TODO: Добавьте сюда любой код прорисовки, использующий HDC...
            EndPaint(hWnd, &ps);
        }
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

// Обработчик сообщений для окна "О программе".
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    UNREFERENCED_PARAMETER(lParam);
    switch (message)
    {
    case WM_INITDIALOG:
        return (INT_PTR)TRUE;

    case WM_COMMAND:
        if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
        {
            EndDialog(hDlg, LOWORD(wParam));
            return (INT_PTR)TRUE;
        }
        break;
    }
    return (INT_PTR)FALSE;
}

Щодо завершення так одразу не скажу як краще буде. Можливо по аналогії створити другий список, де вибирати те, що треба завершити.

Подякували: 0xDADA11C7, alona.riaba2

3

Re: Можливість вибору програми, що запускається, з декількох варіантів

Дякую велике))

4

Re: Можливість вибору програми, що запускається, з декількох варіантів

Не запускається код, тому що немає бібліотек:
#include "stdafx.h"
#include "Win32Project1.h"

Якщо можете киньте будь ласка їх вміст або підкажіть як зробити.

5 Востаннє редагувалося Vi (13.05.2017 16:59:51)

Re: Можливість вибору програми, що запускається, з декількох варіантів

А ти в якому компіляторі працюеш?
У мене VS2015. Тож візьми з прикладу до свого проєкту не все, а лише головне.
Виглядати може десь так:

    #include <windows.h>
    #include <stdio.h>
    #include "proc.h"
    LRESULT CALLBACK ProcessesWndProc(HWND, UINT, UINT, LONG);
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
        LPSTR lpszCmdParam, int nCmdShow)
    {
        HWND hWnd;
        WNDCLASS WndClass;
        MSG Msg;
        char szClassName[] = "Processes";
...
        hWnd = CreateWindow(szClassName, "Processes Demo",
            WS_OVERLAPPEDWINDOW,
            CW_USEDEFAULT, CW_USEDEFAULT,
            CW_USEDEFAULT, CW_USEDEFAULT,
            NULL, NULL, hInstance, NULL);
        if (!hWnd)
        {
            MessageBox(NULL, "Cannot create window", "Error", MB_OK);
            return 0;
        }
        
   int xpos = 10;            // Horizontal position of the window.
   int ypos = 10;            // Vertical position of the window.
   int nwidth = 200;          // Width of the window
   int nheight = 200;         // Height of the window
   HWND hwndParent = hWnd; // Handle to the parent window
 
   HWND hWndComboBox = CreateWindow(L"COMBOBOX", TEXT(""),
       CBS_DROPDOWN | CBS_HASSTRINGS | WS_CHILD | WS_OVERLAPPED | WS_VISIBLE,
       xpos, ypos, nwidth, nheight, hWnd , NULL, hInstance,
       NULL);
   SendMessage(hWndComboBox, (UINT)CB_ADDSTRING, (WPARAM)0, (LPARAM)TEXT("Notepad.exe"));
   SendMessage(hWndComboBox, (UINT)CB_ADDSTRING, (WPARAM)0, (LPARAM)TEXT("calc.exe"));
...
        return Msg.wParam;
    }
    LRESULT CALLBACK ProcessesWndProc(HWND hWnd, UINT Message,
        UINT wParam, LONG lParam)
    {
...
        switch (Message)
        {
        case WM_CREATE:
            hSubMenu = GetSubMenu(GetMenu(hWnd), 0);
            return 0;
        case WM_COMMAND:
        
        if (HIWORD(wParam) == CBN_SELCHANGE) {
            int ItemIndex = SendMessage((HWND)lParam, (UINT)CB_GETCURSEL,(WPARAM)0, (LPARAM)0);
            TCHAR  ListItem[256];
            (TCHAR)SendMessage((HWND)lParam, (UINT)CB_GETLBTEXT,(WPARAM)ItemIndex, (LPARAM)ListItem);
            STARTUPINFO StartupInfo;
            StartupInfo.cb = sizeof(STARTUPINFO);
            StartupInfo.lpReserved = NULL;
            StartupInfo.lpDesktop = NULL;
            StartupInfo.lpTitle = NULL;
            StartupInfo.dwFlags = STARTF_USESHOWWINDOW;
            StartupInfo.wShowWindow = SW_SHOWNORMAL;
            StartupInfo.cbReserved2 = 0;
            StartupInfo.lpReserved2 = NULL;
            PROCESS_INFORMATION ProcessInformation;
            CreateProcess(NULL, (LPWSTR)ListItem,
                NULL, NULL, FALSE, 0,
                NULL, NULL, &StartupInfo,
                &(ProcessInformation));
            break;
        };
        
            switch (LOWORD(wParam))
            {
            case IDM_New_Process:
...
        return DefWindowProc(hWnd, Message, wParam, lParam);
    }

6 Востаннє редагувалося LoganRoss (13.05.2017 19:05:38)

Re: Можливість вибору програми, що запускається, з декількох варіантів

Давайте поясню. А то берете готове і не намагаєтесь навіть розібратися в тому.

#include "stdafx.h"

Це передкомпільований заголовок, який включає в себе заголовочні файли, щоби не прописувати їх в кожному файлі.
Щоб створити такий файл, заходите в властивості (Properties) проекту -> C/C++ -> Precompiled Headers -> вибираєте Use (/Yu).
Після цього створюєте заголовочний файл stdafx.h, в якому можете прописувати бібліотеки і заголовочні файли, що ви підключаєте в програмі.
Потім створюєете виконуваний файл stdafx.cpp, в якому є тільки один рядок:

#include "stdafx.h"

Після цього заходите у властивості файлу stdafx.cpp -> C/C++ -> Precompiled Headers -> вибираєте Create (/Yc).
Тепер можна включати заголовочний файл у всі інші файли (звісно є деякі особливості, при яких варто створювати два і більше такі файли і включати їх у відповідності до використання, але це не у вашому випадку). 
Приклад вмістимого stdafx.h

#include <iostream>
#include <vector>
#include <algorithm>
#include <windows.h>
#include <ctime>
#include <cstdlib>

// Keys
//
#define KEY_UP 72
#define KEY_DOWN 80
#define KEY_LEFT 75
#define KEY_RIGHT 77
#define ESC 27
#define E 69
#define R 82
#define Y 89
#define N 78

І при включенні #include "stdafx.h" - пишіть в першому рядку.

Заголовочний файл Win32Project1.h - це файл, який створюєте ви і по замовчуванню він має ім'я Win32Project<номер>.h, якщо ви не вказали свою назву. Так що це вже питання до вас що в тому файлі.

P.S. В stdafx.h краще не включати файли, які змінюються, тобто ті які ви самі створюєте, а тільки системні.

Подякували: 0xDADA11C71

7

Re: Можливість вибору програми, що запускається, з декількох варіантів

В мене компілятор VS2017, був 2013, але ліцензія закінчилась.