Фоновое изображение для представления навигации

Windows

Некоторые вышеупомянутые значения легко доступны от соответствующего API WIN32, я просто перечисляю их здесь для полноты. Другие, однако, должны быть получены из библиотеки Performance Data Helper (PDH), который "немного неинтуитивен" и берет большой болезненный метод проб и ошибок для взятий за работу. (По крайней мере, это взяло меня долгое время, возможно, я был только немного глуп...)

Примечание: для ясности вся проверка ошибок была опущена от следующего кода. Действительно проверьте коды возврата...!


  • Общая Виртуальная память:

    #include "windows.h"
    
    MEMORYSTATUSEX memInfo;
    memInfo.dwLength = sizeof(MEMORYSTATUSEX);
    GlobalMemoryStatusEx(&memInfo);
    DWORDLONG totalVirtualMem = memInfo.ullTotalPageFile;
    

    Примечание: имя "TotalPageFile" является немного вводящим в заблуждение здесь. В действительности этот параметр дает "Размер Виртуальной памяти", который является размером файла подкачки плюс установленная RAM.

  • Виртуальная память в настоящее время использовала:

    Тот же код как в "Общей Виртуальной памяти" и затем

    DWORDLONG virtualMemUsed = memInfo.ullTotalPageFile - memInfo.ullAvailPageFile;
    
  • Виртуальная память, в настоящее время используемая текущим процессом:

    #include "windows.h"
    #include "psapi.h"
    
    PROCESS_MEMORY_COUNTERS_EX pmc;
    GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc));
    SIZE_T virtualMemUsedByMe = pmc.PrivateUsage;
    



  • Общая Физическая память (RAM):

    Тот же код как в "Общей Виртуальной памяти" и затем

    DWORDLONG totalPhysMem = memInfo.ullTotalPhys;
    
  • Физическая память в настоящее время использовала:

    Same code as in "Total Virtual Memory" and then
    
    DWORDLONG physMemUsed = memInfo.ullTotalPhys - memInfo.ullAvailPhys;
    
  • Физическая память, в настоящее время используемая текущим процессом:

    Тот же код как в "Виртуальной памяти, в настоящее время используемой текущим процессом" и затем

    SIZE_T physMemUsedByMe = pmc.WorkingSetSize;
    



  • , ЦП в настоящее время использовал:

    #include "TCHAR.h"
    #include "pdh.h"
    
    static PDH_HQUERY cpuQuery;
    static PDH_HCOUNTER cpuTotal;
    
    void init(){
        PdhOpenQuery(NULL, NULL, &cpuQuery);
        // You can also use L"\\Processor(*)\\% Processor Time" and get individual CPU values with PdhGetFormattedCounterArray()
        PdhAddEnglishCounter(cpuQuery, L"\\Processor(_Total)\\% Processor Time", NULL, &cpuTotal);
        PdhCollectQueryData(cpuQuery);
    }
    
    double getCurrentValue(){
        PDH_FMT_COUNTERVALUE counterVal;
    
        PdhCollectQueryData(cpuQuery);
        PdhGetFormattedCounterValue(cpuTotal, PDH_FMT_DOUBLE, NULL, &counterVal);
        return counterVal.doubleValue;
    }
    
  • ЦП, в настоящее время используемый текущим процессом:

    #include "windows.h"
    
    static ULARGE_INTEGER lastCPU, lastSysCPU, lastUserCPU;
    static int numProcessors;
    static HANDLE self;
    
    void init(){
        SYSTEM_INFO sysInfo;
        FILETIME ftime, fsys, fuser;
    
        GetSystemInfo(&sysInfo);
        numProcessors = sysInfo.dwNumberOfProcessors;
    
        GetSystemTimeAsFileTime(&ftime);
        memcpy(&lastCPU, &ftime, sizeof(FILETIME));
    
        self = GetCurrentProcess();
        GetProcessTimes(self, &ftime, &ftime, &fsys, &fuser);
        memcpy(&lastSysCPU, &fsys, sizeof(FILETIME));
        memcpy(&lastUserCPU, &fuser, sizeof(FILETIME));
    }
    
    double getCurrentValue(){
        FILETIME ftime, fsys, fuser;
        ULARGE_INTEGER now, sys, user;
        double percent;
    
        GetSystemTimeAsFileTime(&ftime);
        memcpy(&now, &ftime, sizeof(FILETIME));
    
        GetProcessTimes(self, &ftime, &ftime, &fsys, &fuser);
        memcpy(&sys, &fsys, sizeof(FILETIME));
        memcpy(&user, &fuser, sizeof(FILETIME));
        percent = (sys.QuadPart - lastSysCPU.QuadPart) +
            (user.QuadPart - lastUserCPU.QuadPart);
        percent /= (now.QuadPart - lastCPU.QuadPart);
        percent /= numProcessors;
        lastCPU = now;
        lastUserCPU = user;
        lastSysCPU = sys;
    
        return percent * 100;
    }
    
<час>

Linux

На Linux выбор, который казался очевидным сначала, состоял в том, чтобы использовать API POSIX как [1 116] и т.д. Я провел некоторое время, пытаясь заставить это работать, но никогда не получал значимые значения. Когда я наконец проверил сами источники ядра, я узнал, что, по-видимому, эти API полностью еще не реализованы с ядра Linux 2.6!?

В конце я получил все значения через комбинацию чтения псевдофайловой системы /proc и вызовы ядра.

  • Общая Виртуальная память:

    #include "sys/types.h"
    #include "sys/sysinfo.h"
    
    struct sysinfo memInfo;
    
    sysinfo (&memInfo);
    long long totalVirtualMem = memInfo.totalram;
    //Add other values in next statement to avoid int overflow on right hand side...
    totalVirtualMem += memInfo.totalswap;
    totalVirtualMem *= memInfo.mem_unit;
    
  • Виртуальная память в настоящее время использовала:

    Тот же код как в "Общей Виртуальной памяти" и затем

    long long virtualMemUsed = memInfo.totalram - memInfo.freeram;
    //Add other values in next statement to avoid int overflow on right hand side...
    virtualMemUsed += memInfo.totalswap - memInfo.freeswap;
    virtualMemUsed *= memInfo.mem_unit;
    
  • Виртуальная память, в настоящее время используемая текущим процессом:

    #include "stdlib.h"
    #include "stdio.h"
    #include "string.h"
    
    int parseLine(char* line){
        // This assumes that a digit will be found and the line ends in " Kb".
        int i = strlen(line);
        const char* p = line;
        while (*p <'0' || *p > '9') p++;
        line[i-3] = '\0';
        i = atoi(p);
        return i;
    }
    
    int getValue(){ //Note: this value is in KB!
        FILE* file = fopen("/proc/self/status", "r");
        int result = -1;
        char line[128];
    
        while (fgets(line, 128, file) != NULL){
            if (strncmp(line, "VmSize:", 7) == 0){
                result = parseLine(line);
                break;
            }
        }
        fclose(file);
        return result;
    }
    



  • Общая Физическая память (RAM):

    Тот же код как в "Общей Виртуальной памяти" и затем

    long long totalPhysMem = memInfo.totalram;
    //Multiply in next statement to avoid int overflow on right hand side...
    totalPhysMem *= memInfo.mem_unit;
    
  • Физическая память в настоящее время использовала:

    Тот же код как в "Общей Виртуальной памяти" и затем

    long long physMemUsed = memInfo.totalram - memInfo.freeram;
    //Multiply in next statement to avoid int overflow on right hand side...
    physMemUsed *= memInfo.mem_unit;
    
  • Физическая память, в настоящее время используемая текущим процессом:

    Изменение getValue () в "Виртуальной памяти, в настоящее время используемой текущим процессом" следующим образом:

    int getValue(){ //Note: this value is in KB!
        FILE* file = fopen("/proc/self/status", "r");
        int result = -1;
        char line[128];
    
        while (fgets(line, 128, file) != NULL){
            if (strncmp(line, "VmRSS:", 6) == 0){
                result = parseLine(line);
                break;
            }
        }
        fclose(file);
        return result;
    }
    



  • ЦП в настоящее время использовал:

    #include "stdlib.h"
    #include "stdio.h"
    #include "string.h"
    
    static unsigned long long lastTotalUser, lastTotalUserLow, lastTotalSys, lastTotalIdle;
    
    void init(){
        FILE* file = fopen("/proc/stat", "r");
        fscanf(file, "cpu %llu %llu %llu %llu", &lastTotalUser, &lastTotalUserLow,
            &lastTotalSys, &lastTotalIdle);
        fclose(file);
    }
    
    double getCurrentValue(){
        double percent;
        FILE* file;
        unsigned long long totalUser, totalUserLow, totalSys, totalIdle, total;
    
        file = fopen("/proc/stat", "r");
        fscanf(file, "cpu %llu %llu %llu %llu", &totalUser, &totalUserLow,
            &totalSys, &totalIdle);
        fclose(file);
    
        if (totalUser < lastTotalUser || totalUserLow < lastTotalUserLow ||
            totalSys < lastTotalSys || totalIdle < lastTotalIdle){
            //Overflow detection. Just skip this value.
            percent = -1.0;
        }
        else{
            total = (totalUser - lastTotalUser) + (totalUserLow - lastTotalUserLow) +
                (totalSys - lastTotalSys);
            percent = total;
            total += (totalIdle - lastTotalIdle);
            percent /= total;
            percent *= 100;
        }
    
        lastTotalUser = totalUser;
        lastTotalUserLow = totalUserLow;
        lastTotalSys = totalSys;
        lastTotalIdle = totalIdle;
    
        return percent;
    }
    
  • ЦП, в настоящее время используемый текущим процессом:

    #include "stdlib.h"
    #include "stdio.h"
    #include "string.h"
    #include "sys/times.h"
    #include "sys/vtimes.h"
    
    static clock_t lastCPU, lastSysCPU, lastUserCPU;
    static int numProcessors;
    
    void init(){
        FILE* file;
        struct tms timeSample;
        char line[128];
    
        lastCPU = times(&timeSample);
        lastSysCPU = timeSample.tms_stime;
        lastUserCPU = timeSample.tms_utime;
    
        file = fopen("/proc/cpuinfo", "r");
        numProcessors = 0;
        while(fgets(line, 128, file) != NULL){
            if (strncmp(line, "processor", 9) == 0) numProcessors++;
        }
        fclose(file);
    }
    
    double getCurrentValue(){
        struct tms timeSample;
        clock_t now;
        double percent;
    
        now = times(&timeSample);
        if (now <= lastCPU || timeSample.tms_stime < lastSysCPU ||
            timeSample.tms_utime < lastUserCPU){
            //Overflow detection. Just skip this value.
            percent = -1.0;
        }
        else{
            percent = (timeSample.tms_stime - lastSysCPU) +
                (timeSample.tms_utime - lastUserCPU);
            percent /= (now - lastCPU);
            percent /= numProcessors;
            percent *= 100;
        }
        lastCPU = now;
        lastSysCPU = timeSample.tms_stime;
        lastUserCPU = timeSample.tms_utime;
    
        return percent;
    }
    
<час>

TODO: Другие Платформы

я принял бы, что часть кода Linux также работает на Unixe, за исключением частей, которые читают/proc псевдофайловую систему. Возможно, на Unix эти части могут быть заменены [1 118] и подобные функции? Если кто-то с ноу-хау Unix мог бы отредактировать этот ответ и заполнить детали?!

10
задан Community 8 February 2017 в 14:12
поделиться

6 ответов

Я делаю именно это в своем приложении. В AppDelegate у меня есть этот код:

@implementation UINavigationBar (CustomImage)
- (void)drawRect:(CGRect)rect
{
  UIImage *image = [UIImage imageNamed: @"custom_nav_bar.png"];
  [image drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
}
@end
24
ответ дан 3 December 2019 в 14:25
поделиться

К сожалению, в iPhone OS 3.0 или любых предыдущих версиях нет поддержки для использования пользовательских фоновых изображений на панели навигации. Единственный способ настроить внешний вид - установить стиль и цвет оттенка. Я знаю, что не идеально.

В вашем коде вы пытаетесь растянуть заголовок панели навигации, чтобы «пройти под» правой кнопкой. Но это невозможно, поскольку три вида панели навигации (кнопка «Назад», заголовок и правая кнопка) должны находиться на одном слое и настроены таким образом, чтобы они не перекрывались. Это особенность.

Я знаю, что есть ряд сторонних приложений, которые изменяют фоновое изображение, но они «взламывают» систему и используют неподдерживаемые частные API: s или предположения о внутренних структурах данных панели навигации. Эти программы, скорее всего, выйдут из строя (вылетят или будут отображаться некорректно) в будущих версиях iPhone OS.

Скорее всего, вы не хотите связываться с этим. Примите тот факт, что у вас (пока) нет настраиваемого фонового изображения на панели навигации. Я знаю, это больно. Но если вы взломаете систему и ваше приложение выйдет из строя в будущих версиях ОС, Apple заберет приложение из магазина приложений, и вы потеряете весь доход, пока не измените приложение. Это ваш звонок ...

Apple заберет приложение из магазина приложений, и вы потеряете весь доход, пока не измените приложение. Это ваш звонок ...

Apple заберет приложение из магазина приложений, и вы потеряете весь доход, пока не измените приложение. Это ваш звонок ...

-2
ответ дан 3 December 2019 в 14:25
поделиться

Я модифицировал версия Mike Rundle , чтобы настроить настраиваемое изображение можно установить при необходимости. Я также объединился в 40LB-Suit-of-Bees, предлагаемые изменениями. Инициагирование должно быть вызвано во время инициализации:

//UINavigationBar+CustomImage.h
#import <Foundation/Foundation.h>

@interface UINavigationBar(CustomImage)
+ (void) initImageDictionary;
- (void) drawRect:(CGRect)rect;
- (void) setImage:(UIImage*)image;
@end


//UINavigationBar+CustomImage.m    
#import "UINavigationBar+CustomImage.h"
//Global dictionary for recording background image
static NSMutableDictionary *navigationBarImages = NULL;

@implementation UINavigationBar(CustomImage)
//Overrider to draw a custom image

+ (void)initImageDictionary
{
    if(navigationBarImages==NULL){
        navigationBarImages=[[NSMutableDictionary alloc] init];
    }   
}

- (void)drawRect:(CGRect)rect
{
    NSString *imageName=[navigationBarImages objectForKey:[NSValue valueWithNonretainedObject: self]];
    if (imageName==nil) {
        imageName=@"header_bg.png";
    }
    UIImage *image = [UIImage imageNamed: imageName];
    [image drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
}

//Allow the setting of an image for the navigation bar
- (void)setImage:(UIImage*)image
{
    [navigationBarImages setObject:image forKey:[NSValue valueWithNonretainedObject: self]];
}
@end
9
ответ дан 3 December 2019 в 14:25
поделиться

Код Майка Рандла и Кейсбаша великолепен. Я использовал [NSValue valueWithNonrehibitedObject: self], чтобы избежать ошибки copyWithZone. Заключение себя в объект NSValue позволяет скопировать его в словарь navigationBarImages.


- (void)drawRect:(CGRect)rect
{
    NSString *imageName=[navigationBarImages objectForKey:[NSValue valueWithNonretainedObject:self]];
...}


- (void)setImage:(NSString*)image
{
    [navigationBarImages setObject:image forKey:[NSValue valueWithNonretainedObject:self]];
}
1
ответ дан 3 December 2019 в 14:25
поделиться
1
ответ дан 3 December 2019 в 14:25
поделиться
Другие вопросы по тегам:

Похожие вопросы: